blackode
Jason.decode/1 (native, spawned) vs NimblePool-based parser pool — 500 concurrent 1MB+ JSON payloads
Issue: Response count mismatch in decode function under concurrent load
Setup: 4-node cluster, 500 concurrent HTTP requests dispatched via Task.async. All requests return within 2ms max latency.
Problem: Instrumented the decode function with entry/exit log markers. Entry log shows all 500 invocations as expected, but exit log shows only ~179 completions — roughly 64% of decode calls are not reaching the exit log point.
I am using Task.yield_many(spec.kill_cutoff_time_ms) with 4.5 seconds as timeout here. Each task will make http request and decode call Jason.decode
I have tried with Nimble ParserPool but I could reach only 232 at maximum on 64 Core system with pool size of
200
Here is the ParserPool.
defmodule GrncHub.ParserPool do
@behaviour NimblePool
require Logger
@pool_size 500
def child_spec(opts) do
%{
id: **MODULE**,
start: {**MODULE**, :start_link, \[opts\]},
type: :worker,
restart: :permanent,
shutdown: 500
}
end
def start_link(\_) do
NimblePool.start_link(worker: {**MODULE**, nil}, pool_size: @pool_size, name: **MODULE**)
end
@impl true
def init_worker(pool_state), do: {:ok, nil, pool_state}
@impl true
def handle_checkout(:parse, \_from, worker_state, pool_state) do
{:ok, worker_state, worker_state, pool_state}
end
@impl true
def terminate_worker(\_reason, _worker_state, pool_state) do
{:ok, pool_state}
end
@doc """
Returns {:ok, decoded} | {:error, :invalid_json} | {:error, :worker_crashed} | {:error, :invalid_input}
"""
def parse(payload, content_type, parser) when is_binary(payload) do
parser = default_parser(content_type, parser)
try do
NimblePool.checkout!(
__MODULE__,
:parse,
fn _from, worker_state ->
{GrncHub.Parser.decode(payload, content_type, parser), worker_state}
end,
:infinity
)
catch
:exit, reason ->
Logger.error("ParsePool worker crashed: #{inspect(reason)}")
{:error, %{"error" => "worker_crashed"}}
end
end
def parse(\_invalid), do: {:error, %{"error" => "worker_crashed"}}
defp default_parser(:json, nil), do: Jason
defp default_parser(\_content_type, parser), do: parser
end
Trending in Discussions
As the title says, please share what you’ve been up to with Elixir. Whether that’s been learning it, looking into it, making stuff with i...
New
@chrismccord : I just saw the Extract AGENTS.md from Phoenix.new into phx.new generator commit to the phoenix project.
My initial shotgu...
New
I was working on an Ecto migration and I needed a timestamp. So, for the nth time, I looked up the different data types for timestamps, a...
New
Just a general thread to post chat/news/info relating to AI/ML stuff that may be relevant for Nx now or in the future. Got anything to sh...
New
I just stumbled on a newly redesigned elixir-lang.org. :tada: It looks like @Software_Mansion did the work, and I think it is generally a...
New
There has been a thread to discuss the Stack Overflow Developer Survey on this forum every year since 2018, so here’s yet another one for...
New
Fly’s CEO posted this recently - Turn And Face The Strange · The Fly Blog
It says that Fly is going all-in on sprites, which is a worry ...
New
Other Trending Topics
Hey, I’m Jesse and I’m the main contributor behind Dexter, a full-featured, lightning-fast Elixir LSP optimized for large codebases. It s...
New
Beam Bots (or just BB for short) is a framework for building fault-tolerant robotics applications in Elixir using familiar OTP patterns. ...
New
Hello everyone. After busy few months I am happy to announce v0.1.0 of Emerge & Solve.
They are GUI (Emerge) and State management (S...
New
Emily is an Elixir library that runs Nx computations on Apple’s MLX. Install it as the default Nx backend and Nx, defn, Axon, Nx.Serving,...
New
@hugobarauna and I (Alex Koutmos) have been hard at work on writing a book on Nerves that takes you from simply blinking LEDs to building...
New
Introducing AshStorage! Attachment and file management that slots directly into your resources :smiling_face_with_sunglasses:
I had hope...
New
Chat & Discussions>Discussions
Latest on Elixir Forum
Categories:
Sub Categories:
Forums
Popular Tags
- #ecto
- #liveview
- #troubleshooting
- #learning-elixir
- #deployment
- #library
- #erlang
- #testing
- #genserver
- #mix
- #absinthe
- #remote-other
- #otp
- #plug
- #how-to-question
- #macros
- #postgres
- #channels
- #elixirconf
- #exunit
- #discussion
- #code-sync
- #javascript
- #podcasts
- #onsite
- #dialyzer
- #docker
- #authentication
- #umbrella
- #full-time-contract
- #podcasts-by-brainlid
- #ecto-query
- #elixir-ls
- #phoenix_html
- #iex
- #blog-post
- #graphql
- #genstage
- #ai
- #elixirconf-us
- #websockets
- #supervisor
- #advent-of-code
- #distillery
- #processes
- #api
- #forms
- #metaprogramming
- #performance
- #security










Most Liked
andyleclair
You simply do not need a pool of parser processes. You don’t gain anything by parallelizing the parsing, simply call
JSON.decode!. A pool of processes can help you if the thing you’re doing is IO bound, however, as I stated, JSON parsing is CPU bound and the work cannot be parallelized in that way. You will actually make performance worse by doing this.andyleclair
Since JSON parsing is a CPU-bound task, it’s better to parse the JSON in whatever task process is making the HTTP request, rather than in another set of tasks, since all the data would have to be copied from the HTTP task to the JSON task. Does that make sense? Unfortunately you can’t just throw tasks at things and expect it will magically get faster, and processes have a cost. They’re cheap but not free.
Schultzer
Are you doing actual HTTP request or just benchmarking 500 concurrent processing decoding JSON, I could imagine that the bottleneck being the pool or another place in the framework. There is quite a few places that you can create scheduler starvation and mailbox contention if you don’t use the receive optimization.
But without complete reproducible example no one can help you.
Last Post!
saleyn
Take a look at glazer, which is several times more efficient at parsing large JSON payloads compared to Jason.