Speed up couch_httpd:find_in_binary. See https://issues.apache.org/jira/browse/COUCHDB-1953
Project: http://git-wip-us.apache.org/repos/asf/couchdb/repo Commit: http://git-wip-us.apache.org/repos/asf/couchdb/commit/a4b1aa37 Tree: http://git-wip-us.apache.org/repos/asf/couchdb/tree/a4b1aa37 Diff: http://git-wip-us.apache.org/repos/asf/couchdb/diff/a4b1aa37 Branch: refs/heads/1953-fix-mime-multipart-parsing Commit: a4b1aa37867e83abda88b05d2475f84b3de8df09 Parents: 37c8459 Author: NickNorth <[email protected]> Authored: Tue Dec 3 20:58:53 2013 +0000 Committer: Paul J. Davis <[email protected]> Committed: Fri Jan 24 19:03:00 2014 -0600 ---------------------------------------------------------------------- src/couchdb/couch_httpd.erl | 32 +++++++++++++++++--------------- 1 file changed, 17 insertions(+), 15 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/couchdb/blob/a4b1aa37/src/couchdb/couch_httpd.erl ---------------------------------------------------------------------- diff --git a/src/couchdb/couch_httpd.erl b/src/couchdb/couch_httpd.erl index 465bc7a..11acf1c 100644 --- a/src/couchdb/couch_httpd.erl +++ b/src/couchdb/couch_httpd.erl @@ -1085,27 +1085,29 @@ find_in_binary(_B, <<>>) -> find_in_binary(B, Data) -> case binary:match(Data, [B], []) of nomatch -> - partial_find(binary:part(B, {0, byte_size(B) - 1}), - binary:part(Data, {byte_size(Data), -byte_size(Data) + 1}), 1); + MatchLength = erlang:min(byte_size(B), byte_size(Data)), + match_prefix_at_end(binary:part(B, {0, MatchLength}), + binary:part(Data, {byte_size(Data), -MatchLength}), + MatchLength, byte_size(Data) - MatchLength); {Pos, _Len} -> {exact, Pos} end. -partial_find(<<>>, _Data, _Pos) -> - not_found; - -partial_find(B, Data, N) when byte_size(Data) > 0 -> - case binary:match(Data, [B], []) of - nomatch -> - partial_find(binary:part(B, {0, byte_size(B) - 1}), - binary:part(Data, {byte_size(Data), -byte_size(Data) + 1}), N + 1); - {Pos, _Len} -> - {partial, N + Pos} - end; +match_prefix_at_end(Prefix, Data, PrefixLength, N) -> + FirstCharMatches = binary:matches(Data, [binary:part(Prefix, {0, 1})], []), + match_rest_of_prefix(FirstCharMatches, Prefix, Data, PrefixLength, N). -partial_find(_B, _Data, _N) -> - not_found. +match_rest_of_prefix([], _Prefix, _Data, _PrefixLength, _N) -> + not_found; +match_rest_of_prefix([{Pos, _Len} | Rest], Prefix, Data, PrefixLength, N) -> + case binary:match(binary:part(Data, {PrefixLength, Pos - PrefixLength}), + [binary:part(Prefix, {0, PrefixLength - Pos})], []) of + nomatch -> + match_rest_of_prefix(Rest, Prefix, Data, PrefixLength, N); + {_Pos, _Len1} -> + {partial, N + Pos} + end. validate_bind_address(Address) -> case inet_parse:address(Address) of
