以下是来自Google Protobuf Documents里的一句话:
As you can see, each field in the message definition has a unique numbered tag. These tags are used to identify your fields in the
message binary format, and should not be changed once your message type is in use. Note that tags with values in the range 1 through 15 take one byte to encode. Tags in the range 16 through 2047 take two bytes. So you should reserve the tags 1 through 15 for very frequently occurring message elements. Remember to leave some room for frequently occurring elements that might be added in the future.
这里要做一个解释,就是为什么是1到15,以及16到2047呢?
- 1到15,仅使用1bytes。每个byte包含两个部分,一个是field_number一个是tag,其中field-number就是protobuf中每个值后等号后的数字(在C++和Java中,如果不设置这个值,则它是随机的,如果在Python中,不设置,它则不被处理(这个在message binary format中的Field Order一节中有提到)。那么我们可以认为这个field_number是必须的。那么一个byte用来表达这个值就是000000000,其中红色表示是否有后续字节,如果为0表示没有也就是这是一个字节,蓝色部分表示field-number,绿色部分则是wire_type部分,表示数据类型。也就是(field_number << 3) | wire_type。其中wire_type只有3位,表示数据类型。那么能够表示field_number的就是5位蓝色的数字,5位数字能够表达的最大范围就是1-15(其中0是无效的)。
- 16到2047,与上面的规则其实类似,下面以2bytes为例子,那么就有10000000 00000000,其中红色部分依然是符号位,因为每个byte的第一位都用来表示下一byte是否和自己有关,那么对于>1byte的数据,第一位一定是1,因为这里假设是2byte,那么第二个byte的第一位也是红色,刨除这两位,再扣掉3个wire_type位,剩下11位(2*8-2-3),能够表达的数字范围就是2047(211)。
参考资料:
- http://code.google.com/intl/zh-CN/apis/protocolbuffers/docs/proto.html
- http://code.google.com/apis/protocolbuffers/docs/encoding.html