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

Reply via email to