Reputation: 87
We are using protobuf as our messaging, and each message, we loop thru the set fields, and do something with it.
We loop it using
for ( final Map.Entry<Descriptors.FieldDescriptor, Object> entry : msg.getAllFields().entrySet()) {
FieldDescriptor field = entry.getKey();
Object value = entry.getValue();
Under profiler, we found that this GetAllFields uses most of the time, and I did some research, and it looks like there is no other way.
I know that we can use do something like this:
for ( final FieldDescriptor field : msg.getDescriptorForType().getFields()) {
if (!msg.hasField(field)){
continue;
}
Object value = message.getField(field);
But getDescriptorForType returns all the fields rather than just the set ones.
Does anyone know of another better performing way to loop thru the fields? I believe the problem with getAllFields are creating a new map each time, and also reflection. Can i force it to use Trove map inside rather than a regular hashmap?
Thanks.
Upvotes: 4
Views: 2992
Reputation: 45151
getAllFields()
is part of Protobuf's reflection interface (not to be confused with Java's reflection). Protobuf reflection is, alas, quite slow -- it's essentially like using an interpreted language rather than a compiled one.
If you need your code to be fast, the way to do it is to call the generated-code methods directly. Unfortunately this can be tedious if you're doing something repetitive to every field. One thing you might consider is writing a code generator plugin for protoc
to auto-generate the repetitive code (much like protoc
generates code for the protobuf classes themselves). For more on how to do that, see the docs on descriptor.proto.
Upvotes: 5