2011-03-06 3 views
3

다음과 같은 프로토콜 버퍼 설정이 있습니다.프로토콜 버퍼 배열의 낭비 된 바이트?

[ProtoContract] 
Foo 
{ 
    [ProtoMember(1)] 
    Bar[] Bars; 
} 

단일 막대는 67 바이트 프로토콜 버퍼로 인코딩됩니다. Bar가 거의 64 바이트 배열이라는 것을 알고 있기 때문에 길이에 대한 3 바이트 오버 헤드가 있습니다.

그러나 20 개의 막대 배열을 가진 Foo를 인코딩 할 때 1362 바이트가 필요합니다. 20 * 67은 1340이므로 배열을 인코딩하는 데 단지 22 바이트의 오버 헤드가 있습니다!

왜 이렇게 많은 공간을 차지합니까? 그리고 그것을 줄이기 위해 내가 할 수있는 일이 있습니까?

+1

Foo 자체는 무료입니까? 또한 약간의 공간이 필요합니까? – user492238

+0

약간의 공간이 필요하지만 22 바이트는 많은 공간입니다! – Martin

+2

1340의 상단에있는 22 바이트는 '순전히'아니며, 분명히 직렬화를위한 것이 아닙니다. 너의 인생을 따라 가라. –

답변

5

이 오버 헤드는 아주 간단하게는 20 각 개체가 시작하고 끝나는 위치를 알 필요가있는 정보입니다. 형식을 위반하지 않고 여기에서 다른 작업을 수행 할 수있는 방법은 없습니다 (예 : 사양과 반대되는 작업).

당신은 정말 처참한 세부하려면 다음

배열 또는 목록 (우리가 제외하면 "포장"여기에 적용되지 않습니다) 서브 메시지를 단순히 반복 블록을. 하위 메시지에는 두 가지 레이아웃이 있습니다. 문자열 및 그룹. 끈으로, 레이아웃은 :

header가 (필드 1이 경우 육각 08), 와이어 형의 필드 번호의 varint 부호화 매쉬이다
[header][length][data] 

, length는 varint 인코딩 크기는 data이고 데이터는 하위 오브젝트 자체입니다. 작은 개체 (data 128 바이트 미만)의 경우 필드 번호 (15보다 큰 필드는 더 많은 공간을 차지함) 및 b : 데이터의 크기에 따라 개체 당 2 바이트의 오버 헤드를 의미합니다. 기로

는, 레이아웃은 : header가 와이어 타입 및 필드 번호 (필드 1이 경우 육각 0B)의 varint 부호화 매쉬이다

[header][data][footer] 

, data가있다 하위 오브젝트 및 footer은 오브젝트의 끝을 나타내는 또 다른 varint mash입니다 (이 경우 필드 1의 경우 16 진수 0C).

그룹은 일반적으로 덜 선호되지만, data 크기가 커지면 오버 헤드가 발생하지 않는다는 이점이 있습니다. 작은 필드 번호 (16 미만)의 경우 오버 헤드는 객체 당 2 바이트입니다. 물론 큰 필드 번호에 대해서는 두 배를 지불해야합니다.

+0

Marc에게 감사의 말을 전합니다. Marc의 프로토콜에 대해 불쾌한 사례가 될 수 있습니다. – Martin

2

기본적으로 배열은 실제로는 배열로 전달되지 않지만 반복되는 멤버는 약간의 오버 헤드가 있습니다.

그래서 나는 반복되는 각 배열 요소에 대해 실제로 1 바이트의 오버 헤드와 2 개의 여분의 바이트 오버 헤드가있는 것 같아요.

"압축 된"배열을 사용하면 오버 헤드가 손실 될 수 있습니다. protobuf - 그물 지원이 : http://code.google.com/p/protobuf-net/

바이너리 형식의 문서가 여기에 있습니다 : http://code.google.com/apis/protocolbuffers/docs/encoding.html

+0

Odd, 배열에서 packed를 사용하면 "packed buffers are wire-type : String"예외가 트리거됩니다. Bar가 문자열이 아니기 때문에 어느 것이 이상합니다! – Martin

+1

@ 마틴 - protobuf 스펙에 관한 한 : 그렇습니다. 이는 특정 레이아웃의 이름 일 뿐이며 * 텍스트 * 문자열을 의미하지는 않습니다. 오브젝트에는 두 가지 형식이 있습니다. 문자열 및 그룹. Packed는 실제로 머리글의 오버 헤드를 제거하지만 정수와 부동 소수점과 같은 매우 기본적인 유형에만 적용됩니다. 물건이 아닙니다. –