Remove dynamic apply/3 call when it's not needed#1321
Conversation
|
Unfortunately this pull request is fundamentally broken: the init can happen at compile-time, which means a different environment than the one that calls |
|
I could include the benchmark if you'd like, but if the init could be called at compile time, this is indeed a improper PR suggestion. |
|
I pushed a fix that inlines some of the calls but yes, the approach here is definitely wrong, so no benchmarks needed for this PR. :) |
|
I'll take a look at your change. This was another version I tried prior to making the PR, which was still slightly better than current, but slightly worse than the persistent_term cached approach: defmodule Plug.Parsers.JSONLean do
@moduledoc """
Optimized JSON parser without persistent_term.
"""
@behaviour Plug.Parsers
# Accept both old and new Plug decoder formats
def init(opts) do
decoder =
case Keyword.get(opts, :json_decoder, Jason) do
mod when is_atom(mod) ->
# Old Plug API: json_decoder: Jason
&mod.decode!/1
{mod, fun, extra} ->
# MFA form: json_decoder: {Jason, :decode!, []}
fn body -> apply(mod, fun, [body | extra]) end
end
%{decoder: decoder}
end
def parse(conn, "application", subtype, _headers, %{decoder: decoder}) do
if subtype == "json" or String.ends_with?(subtype, "+json") do
decode_body(conn, decoder)
else
{:next, conn}
end
end
def parse(conn, _type, _subtype, _headers, _opts) do
{:next, conn}
end
defp decode_body(conn, decoder) do
case Plug.Conn.read_body(conn) do
{:ok, body, conn} ->
try do
terms = decoder.(body)
{:ok, normalize(terms), conn}
rescue
_ -> raise Plug.Parsers.ParseError
end
{:more, _, _} ->
raise Plug.Parsers.ParseError
end
end
# Match Plug behavior: wrap non-map JSON in "_json"
defp normalize(%{} = map), do: map
defp normalize(other), do: %{"_json" => other}
end |
|
I did look at your change, and it indeed addresses the same concern. So all good :) |
Implements a high‑performance Plug JSON parser variant that:
persistent_termPlug.Parserscompatibility and error semanticsBenchmarks show ~10% improvement on medium/large JSON payloads.