aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLoïc Hoguin <[email protected]>2011-03-27 01:16:11 +0100
committerLoïc Hoguin <[email protected]>2011-03-27 01:16:11 +0100
commitd0d9b0e8b363b456bd0b9e5fbdebc90f055546c3 (patch)
treef6692301fa8f811ad3e8c042875bd576aba290f1
parent5726aa3d85c0b8642b90d698b15fee8e5a0281fb (diff)
downloadcowboy-d0d9b0e8b363b456bd0b9e5fbdebc90f055546c3.tar.gz
cowboy-d0d9b0e8b363b456bd0b9e5fbdebc90f055546c3.tar.bz2
cowboy-d0d9b0e8b363b456bd0b9e5fbdebc90f055546c3.zip
Use a more efficient variant of string:to_lower to improve performance.
After much testing and experimentation of all kinds I find lists to be both faster and using less memory than binaries for request-line and headers handling. This is more than likely due to the fact that headers are very short and thus do not benefit from the advantages of refc binaries, meaning they're copied, just like lists. The memory usage discrepancy is still a mystery for the most part, although the hoops needed to perform operations on the binaries are probably responsible for the extra memory use. I'm thus giving up on trying to use binaries for request-line and headers. Instead, this commit improves performances even more to the lists code, making lists 5% faster than binaries. Lists are easier to work with too, so I guess it's all a big win for everyone. Of course the request body is still read as a binary, we're using the binary type where it performs best.
-rw-r--r--src/cowboy_http_protocol.erl40
1 files changed, 38 insertions, 2 deletions
diff --git a/src/cowboy_http_protocol.erl b/src/cowboy_http_protocol.erl
index 55ecd34..6242fdd 100644
--- a/src/cowboy_http_protocol.erl
+++ b/src/cowboy_http_protocol.erl
@@ -97,7 +97,7 @@ wait_header(Req, State=#state{socket=Socket,
Value::string()} | http_eoh, Req::#http_req{}, State::#state{}) -> ok.
header({http_header, _I, 'Host', _R, RawHost}, Req=#http_req{path=Path,
host=undefined}, State=#state{dispatch=Dispatch}) ->
- RawHost2 = string:to_lower(RawHost),
+ RawHost2 = string_to_lower(RawHost),
Host = cowboy_dispatcher:split_host(RawHost2),
%% @todo We probably want to filter the Host and Path here to allow
%% things like url rewriting.
@@ -220,7 +220,43 @@ connection_to_atom("keep-alive") ->
connection_to_atom("close") ->
close;
connection_to_atom(Connection) ->
- case string:to_lower(Connection) of
+ case string_to_lower(Connection) of
"close" -> close;
_Any -> keepalive
end.
+
+%% More efficient implementation of string:to_lower.
+%% We are excluding a few characters on purpose.
+-spec string_to_lower(string()) -> string().
+string_to_lower(L) ->
+ [char_to_lower(C) || C <- L].
+
+%% We gain noticeable speed by matching each value directly.
+-spec char_to_lower(char()) -> char().
+char_to_lower($A) -> $a;
+char_to_lower($B) -> $b;
+char_to_lower($C) -> $c;
+char_to_lower($D) -> $d;
+char_to_lower($E) -> $e;
+char_to_lower($F) -> $f;
+char_to_lower($G) -> $g;
+char_to_lower($H) -> $h;
+char_to_lower($I) -> $i;
+char_to_lower($J) -> $j;
+char_to_lower($K) -> $k;
+char_to_lower($L) -> $l;
+char_to_lower($M) -> $m;
+char_to_lower($N) -> $n;
+char_to_lower($O) -> $o;
+char_to_lower($P) -> $p;
+char_to_lower($Q) -> $q;
+char_to_lower($R) -> $r;
+char_to_lower($S) -> $s;
+char_to_lower($T) -> $t;
+char_to_lower($U) -> $u;
+char_to_lower($V) -> $v;
+char_to_lower($W) -> $w;
+char_to_lower($X) -> $x;
+char_to_lower($Y) -> $y;
+char_to_lower($Z) -> $z;
+char_to_lower(Ch) -> Ch.