aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLoïc Hoguin <[email protected]>2019-12-26 15:38:00 +0100
committerLoïc Hoguin <[email protected]>2019-12-26 15:39:09 +0100
commit0575c9aa57df15acbd563062278df28898782688 (patch)
tree2c8e1c1d46c6f67a483ddfda841e55e6a7dd5fcf
parentb21356c62b8360a39244ca1583dd5beb6799b732 (diff)
downloadcowlib-0575c9aa57df15acbd563062278df28898782688.tar.gz
cowlib-0575c9aa57df15acbd563062278df28898782688.tar.bz2
cowlib-0575c9aa57df15acbd563062278df28898782688.zip
HPACK encode: conditionally call an iolist_to_binary
This provides a small but noticeable improvement so it's probably worth doing.
-rw-r--r--src/cow_hpack.erl73
1 files changed, 70 insertions, 3 deletions
diff --git a/src/cow_hpack.erl b/src/cow_hpack.erl
index be8372c..8365795 100644
--- a/src/cow_hpack.erl
+++ b/src/cow_hpack.erl
@@ -511,8 +511,13 @@ encode(Headers, State0=#state{configured_max_size=MaxSize}, Opts) ->
%% @todo Handle cases where no/never indexing is expected.
encode([], State, _, Acc) ->
{lists:reverse(Acc), State};
-encode([_Header0 = {Name, Value0}|Tail], State, Opts, Acc) ->
- Value = iolist_to_binary(Value0),
+encode([{Name, Value0}|Tail], State, Opts, Acc) ->
+ %% We conditionally call iolist_to_binary/1 because a small
+ %% but noticeable speed improvement happens when we do this.
+ Value = if
+ is_binary(Value0) -> Value0;
+ true -> iolist_to_binary(Value0)
+ end,
Header = {Name, Value},
case table_find(Header, State) of
%% Indexed header field representation.
@@ -558,7 +563,7 @@ enc_str(Str, Opts) ->
Str2 = enc_huffman(Str, <<>>),
[enc_int7(byte_size(Str2), 2#1), Str2];
false ->
- [enc_int7(iolist_size(Str), 2#0), Str]
+ [enc_int7(byte_size(Str), 2#0), Str]
end.
enc_huffman(<<>>, Acc) ->
@@ -990,6 +995,68 @@ encode_iolist_test() ->
],
{_, _} = encode(Headers),
ok.
+
+horse_encode_raw() ->
+ horse:repeat(20000,
+ do_horse_encode_raw()
+ ).
+
+do_horse_encode_raw() ->
+ Headers1 = [
+ {<<":method">>, <<"GET">>},
+ {<<":scheme">>, <<"http">>},
+ {<<":path">>, <<"/">>},
+ {<<":authority">>, <<"www.example.com">>}
+ ],
+ {_, State1} = encode(Headers1, init(), #{huffman => false}),
+ Headers2 = [
+ {<<":method">>, <<"GET">>},
+ {<<":scheme">>, <<"http">>},
+ {<<":path">>, <<"/">>},
+ {<<":authority">>, <<"www.example.com">>},
+ {<<"cache-control">>, <<"no-cache">>}
+ ],
+ {_, State2} = encode(Headers2, State1, #{huffman => false}),
+ Headers3 = [
+ {<<":method">>, <<"GET">>},
+ {<<":scheme">>, <<"https">>},
+ {<<":path">>, <<"/index.html">>},
+ {<<":authority">>, <<"www.example.com">>},
+ {<<"custom-key">>, <<"custom-value">>}
+ ],
+ {_, _} = encode(Headers3, State2, #{huffman => false}),
+ ok.
+
+horse_encode_huffman() ->
+ horse:repeat(20000,
+ do_horse_encode_huffman()
+ ).
+
+do_horse_encode_huffman() ->
+ Headers1 = [
+ {<<":method">>, <<"GET">>},
+ {<<":scheme">>, <<"http">>},
+ {<<":path">>, <<"/">>},
+ {<<":authority">>, <<"www.example.com">>}
+ ],
+ {_, State1} = encode(Headers1),
+ Headers2 = [
+ {<<":method">>, <<"GET">>},
+ {<<":scheme">>, <<"http">>},
+ {<<":path">>, <<"/">>},
+ {<<":authority">>, <<"www.example.com">>},
+ {<<"cache-control">>, <<"no-cache">>}
+ ],
+ {_, State2} = encode(Headers2, State1),
+ Headers3 = [
+ {<<":method">>, <<"GET">>},
+ {<<":scheme">>, <<"https">>},
+ {<<":path">>, <<"/index.html">>},
+ {<<":authority">>, <<"www.example.com">>},
+ {<<"custom-key">>, <<"custom-value">>}
+ ],
+ {_, _} = encode(Headers3, State2),
+ ok.
-endif.
%% Static and dynamic tables.