Skip to content

Commit

Permalink
HTTP/2: Optimize check for CONNECT method in header creation
Browse files Browse the repository at this point in the history
`String.upcase/1` by default iterates over the graphemes in the
input string which can be relatively slow. Since we're only interested
in case-insensitive equality, we can write a small custom equality
checking function that can avoid creating new terms and can return
early.

Using a charlist is slightly faster than passing `"CONNECT"` as a
binary.
  • Loading branch information
the-mikedavis committed Feb 3, 2024
1 parent 53e988e commit 7c78455
Showing 1 changed file with 15 additions and 1 deletion.
16 changes: 15 additions & 1 deletion lib/mint/http2.ex
Original file line number Diff line number Diff line change
Expand Up @@ -1360,7 +1360,7 @@ defmodule Mint.HTTP2 do
end

defp add_pseudo_headers(headers, conn, method, path) do
if String.upcase(method) == "CONNECT" do
if is_method?(method, ~c"CONNECT") do
[
{":method", method},
{":authority", authority_pseudo_header(conn)}
Expand All @@ -1377,6 +1377,20 @@ defmodule Mint.HTTP2 do
end
end

@spec is_method?(proposed :: binary(), method :: charlist()) :: boolean()
defp is_method?(<<>>, []), do: true

defp is_method?(<<char, rest_bin::binary>>, [char | rest_list]) do
is_method?(rest_bin, rest_list)
end

defp is_method?(<<lower_char, rest_bin::binary>>, [char | rest_list])
when lower_char >= ?a and lower_char <= ?z and lower_char - 32 == char do
is_method?(rest_bin, rest_list)
end

defp is_method?(_proposed, _method), do: false

defp sort_pseudo_headers_to_front(headers) do
Enum.sort_by(headers, fn {key, _value} ->
not String.starts_with?(key, ":")
Expand Down

0 comments on commit 7c78455

Please sign in to comment.