Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Remove O(N^2) algorithm from repeated field extraction.
In messages with many values for a repeated field, lists:reverse/1 is
called many times, resulting in large amounts of garbage and an
unreasonable amount of time spent in decoding. This moves the list
reversal until the end of the decoding, only once per repeated field.
  • Loading branch information
Sean Cribbs committed Jun 4, 2013
commit 82243b83891dca912213b5e0ae196caab1da0a4e
20 changes: 17 additions & 3 deletions src/pokemon_pb.erl
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ decode(pikachu, Bytes) when is_binary(Bytes) ->
Decoded = decode(Bytes, Types, Defaults),
to_record(pikachu, Decoded).

decode(<<>>, _, Acc) -> Acc;
decode(<<>>, Types, Acc) -> reverse_repeated_fields(Acc, Types);
decode(Bytes, Types, Acc) ->
{ok, FNum} = protobuffs:next_field_num(Bytes),
case lists:keyfind(FNum, 1, Types) of
Expand All @@ -125,12 +125,12 @@ decode(Bytes, Types, Acc) ->
true ->
case lists:keytake(FNum, 1, Acc) of
{value, {FNum, Name, List}, Acc1} ->
decode(Rest1, Types, [{FNum, Name, lists:reverse([int_to_enum(Type,Value1)|lists:reverse(List)])}|Acc1]);
decode(Rest1, Types, [{FNum, Name, [int_to_enum(Type,Value1)|List]}|Acc1]);
false ->
decode(Rest1, Types, [{FNum, Name, [int_to_enum(Type,Value1)]}|Acc])
end;
false ->
decode(Rest1, Types, [{FNum, Name, int_to_enum(Type,Value1)}|Acc])
decode(Rest1, Types, [{FNum, Name, int_to_enum(Type,Value1)}|Acc])
end;
false ->
case lists:keyfind('$extensions', 2, Acc) of
Expand All @@ -147,6 +147,20 @@ decode(Bytes, Types, Acc) ->
end
end.

reverse_repeated_fields(FieldList, Types) ->
[ begin
case lists:keyfind(FNum, 1, Types) of
{FNum, Name, _Type, Opts} ->
case lists:member(repeated, Opts) of
true ->
{FNum, Name, lists:reverse(Value)};
_ ->
Field
end;
_ -> Field
end
end || {FNum, Name, Value}=Field <- FieldList ].

unpack_value(Binary, string) when is_binary(Binary) ->
binary_to_list(Binary);
unpack_value(Value, _) -> Value.
Expand Down