0
Fork 0
mirror of https://github.com/ninenines/cowboy.git synced 2025-07-14 20:30:23 +00:00

Stop using binary:match in cowboy_protocol

It's been found slower than a custom equivalent to what we were
using it for. As this is the critical path we prefer the custom
solution.
This commit is contained in:
Loïc Hoguin 2013-03-06 14:29:28 +01:00
parent 233cf43ab9
commit a930f4ab26

View file

@ -171,20 +171,27 @@ parse_request(<< $\n, _/binary >>, State, _) ->
%% reading from the socket and eventually crashing. %% reading from the socket and eventually crashing.
parse_request(Buffer, State=#state{max_request_line_length=MaxLength, parse_request(Buffer, State=#state{max_request_line_length=MaxLength,
max_empty_lines=MaxEmpty}, ReqEmpty) -> max_empty_lines=MaxEmpty}, ReqEmpty) ->
case binary:match(Buffer, <<"\n">>) of case match_eol(Buffer, 0) of
nomatch when byte_size(Buffer) > MaxLength -> nomatch when byte_size(Buffer) > MaxLength ->
error_terminate(414, State); error_terminate(414, State);
nomatch -> nomatch ->
wait_request(Buffer, State, ReqEmpty); wait_request(Buffer, State, ReqEmpty);
{1, _} when ReqEmpty =:= MaxEmpty -> 1 when ReqEmpty =:= MaxEmpty ->
error_terminate(400, State); error_terminate(400, State);
{1, _} -> 1 ->
<< _:16, Rest/binary >> = Buffer, << _:16, Rest/binary >> = Buffer,
parse_request(Rest, State, ReqEmpty + 1); parse_request(Rest, State, ReqEmpty + 1);
{_, _} -> _ ->
parse_method(Buffer, State, <<>>) parse_method(Buffer, State, <<>>)
end. end.
match_eol(<< $\n, _/bits >>, N) ->
N;
match_eol(<< _, Rest/bits >>, N) ->
match_eol(Rest, N + 1);
match_eol(_, _) ->
nomatch.
parse_method(<< C, Rest/bits >>, State, SoFar) -> parse_method(<< C, Rest/bits >>, State, SoFar) ->
case C of case C of
$\r -> error_terminate(400, State); $\r -> error_terminate(400, State);
@ -261,15 +268,22 @@ parse_header(<< $\r, $\n, Rest/bits >>, S, M, P, Q, F, V, Headers) ->
request(Rest, S, M, P, Q, F, V, lists:reverse(Headers)); request(Rest, S, M, P, Q, F, V, lists:reverse(Headers));
parse_header(Buffer, State=#state{max_header_name_length=MaxLength}, parse_header(Buffer, State=#state{max_header_name_length=MaxLength},
M, P, Q, F, V, H) -> M, P, Q, F, V, H) ->
case binary:match(Buffer, <<":">>) of case match_colon(Buffer, 0) of
nomatch when byte_size(Buffer) > MaxLength -> nomatch when byte_size(Buffer) > MaxLength ->
error_terminate(400, State); error_terminate(400, State);
nomatch -> nomatch ->
wait_header(Buffer, State, M, P, Q, F, V, H); wait_header(Buffer, State, M, P, Q, F, V, H);
{_, _} -> _ ->
parse_hd_name(Buffer, State, M, P, Q, F, V, H, <<>>) parse_hd_name(Buffer, State, M, P, Q, F, V, H, <<>>)
end. end.
match_colon(<< $:, _/bits >>, N) ->
N;
match_colon(<< _, Rest/bits >>, N) ->
match_colon(Rest, N + 1);
match_colon(_, _) ->
nomatch.
%% I know, this isn't exactly pretty. But this is the most critical %% I know, this isn't exactly pretty. But this is the most critical
%% code path and as such needs to be optimized to death. %% code path and as such needs to be optimized to death.
%% %%
@ -336,12 +350,12 @@ parse_hd_before_value(<< $\t, Rest/bits >>, S, M, P, Q, F, V, H, N) ->
parse_hd_before_value(Rest, S, M, P, Q, F, V, H, N); parse_hd_before_value(Rest, S, M, P, Q, F, V, H, N);
parse_hd_before_value(Buffer, State=#state{ parse_hd_before_value(Buffer, State=#state{
max_header_value_length=MaxLength}, M, P, Q, F, V, H, N) -> max_header_value_length=MaxLength}, M, P, Q, F, V, H, N) ->
case binary:match(Buffer, <<"\n">>) of case match_eol(Buffer, 0) of
nomatch when byte_size(Buffer) > MaxLength -> nomatch when byte_size(Buffer) > MaxLength ->
error_terminate(400, State); error_terminate(400, State);
nomatch -> nomatch ->
wait_hd_before_value(Buffer, State, M, P, Q, F, V, H, N); wait_hd_before_value(Buffer, State, M, P, Q, F, V, H, N);
{_, _} -> _ ->
parse_hd_value(Buffer, State, M, P, Q, F, V, H, N, <<>>) parse_hd_value(Buffer, State, M, P, Q, F, V, H, N, <<>>)
end. end.