Protobuf高频使用FieldDescriptor能否缓存其地址替代每次调用FindFieldByName
关于缓存Protobuf FieldDescriptor可行性的解答
这个做法完全可行,属于Protobuf场景下非常常规的性能优化手段,有官方设计作为可靠性保证:
- Protobuf所有官方实现(C++/Java/Go/Python等)的元数据对象(
FileDescriptor/Descriptor/FieldDescriptor等)均为进程内单例:同类型的Protobuf消息必然共享同一套元数据实例,实例生命周期和进程生命周期完全一致,加载后不会发生变更也不会被销毁,你观测到的实例一致的现象是官方设计的结果,不是临时实现特性。 - 直接缓存
FieldDescriptor地址可以规避FindFieldByName接口的字符串匹配开销:FindFieldByName的时间复杂度为O(n)(n为当前消息的字段总数),高频调用场景下的性能损耗非常明显,缓存指针后可以直接O(1)获取字段元数据,优化收益很高。
仅需注意少数边界场景:
- 不要跨进程传递缓存的
FieldDescriptor地址,不同进程的元数据实例地址相互独立 - 如果你的程序存在动态卸载Protobuf生成的动态库(so/dll)的逻辑,需要确保缓存地址对应的动态库未被卸载,避免出现野指针;如果无动态卸载逻辑则完全不需要考虑该问题
- 缓存时建议关联对应消息的
Descriptor做匹配校验,避免不同消息类型的同名字段缓存混淆
内容的提问来源于stack exchange,提问作者user16923816
相关产品推荐
相关产品推荐

