Precompiled Messages
Performance can be improved using a strategy of precompiling the constant portions of your message. Enumerations for example, are excellent candidates for precompilation. Using protobuf_message/3, the precompiled portion of the message is inserted directly in the wire-stream on encode, and is unified with, and removed from the wire-stream on decode. The following shows how the "send_command" example above, can be converted to precompiled form:
send_precompiled_command(Command, Vector, WireCodes) :- basic_vector(Vector, Proto1), % precompiled_message/3 is created by term_expansion precompiled_message(commands(Command), WireCodes, Tail), protobuf_message(protobuf([embedded(3, Proto1)]), Tail). term_expansion(precompile_commands, Clauses) :- findall(precompiled_message(commands(Key), WireCodes, Tail), ( protobufs:commands(Key, _), Proto = protobuf([atom(1, command), enum(2, commands(Key))]), protobuf_message(Proto, WireCodes, Tail) ), Clauses). * * * precompile_commands. % Trigger the term-expansion precompilation
Supplying Your Own Host Type Message Sequences
You can extend the parser to support your own compound host types.
These are treated as first class entities by the parser. That is they
can be used either by themselves, or in repeated
and embedded
clauses just as any other host type would be. You do this by hooking
into the parser and adding your own message_sequence
productions. Your hook eventually calls back into the parser with your
substitution/expansion protobuf, which is then embedded in the wire
stream. Recursive structures can be defined this way. A simple example
of a recursive XML like structure is shown in the appendix.