From 7bb2e5bf376de14cf298d262e723658c7c60747f Mon Sep 17 00:00:00 2001 From: Michael Davis Date: Sat, 3 Feb 2024 15:35:07 -0500 Subject: [PATCH] HTTP/2: Optimize check for CONNECT method in header creation `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. --- lib/mint/http2.ex | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/lib/mint/http2.ex b/lib/mint/http2.ex index fab488d8..36e55934 100644 --- a/lib/mint/http2.ex +++ b/lib/mint/http2.ex @@ -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)} @@ -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_list]) do + is_method?(rest_bin, rest_list) + end + + defp is_method?(<>, [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, ":")