blackode
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
I want to open this thread for you all to discuss and help those who really like Ash but are still hesitant to use it in a real project. ...
New
I am happy to introduce the very α version of the new programming language compiled to BEAM.
Welcome Cure.
It has literally three kille...
New
I’m posting this in response to Jose’s recent tweet (Cr. link) :
People are sleeping on Elixir for a coding harness:
Hot-code swappi...
New
Hello,
I wrote Stop My Hand, a Scattergories-like web application using Phoenix/LiveView as my learning project for Elixir (after readin...
New
It would be helpful to have a list of companies worldwide that hire engineers without prior experience in Elixir. Often, it can be quite ...
New
Anyone running long-lived stateful processes on BEAM? We’re building an AI agent runtime and would love to compare notes.
We’re a small ...
New
Other Trending Topics
Hobbes is a low-level distributed database for the Elixir programming language.
Hobbes provides a simple, safe, and scalable storage lay...
New
Hi there! We created Gust: A task orchestrator inspired by Airflow.
For those who have never heard about Aiflow, it’s a Python-based wor...
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
Corex is an accessible, unstyled UI component library for Phoenix that integrates Zag.js state machines using Vanilla JavaScript and Live...
New
There are three potential reasons for members of this forum to have a look at https://vutuv.de
You are tired or annoyed of LinkedIn.
Yo...
New
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
- #elixirconf
- #channels
- #exunit
- #discussion
- #code-sync
- #podcasts
- #javascript
- #onsite
- #dialyzer
- #docker
- #authentication
- #umbrella
- #full-time-contract
- #podcasts-by-brainlid
- #ecto-query
- #blog-post
- #elixirconf-us
- #elixir-ls
- #ai
- #phoenix_html
- #iex
- #graphql
- #genstage
- #websockets
- #supervisor
- #advent-of-code
- #distillery
- #processes
- #api
- #forms
- #hex
- #security
- #metaprogramming











Showing Posts 1 to 10- Show Best Posts
- Show All (oldest first)
- Show All (newest first)
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.
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.
blackode
Thanks for the prompt response.
I have seen that my cpu can reach maximum of 42 % with 200 pool connections for decoding.
I am doing parsing inside the main task which is making http request and as soon as response received, I am calling
ParserPool.parse()My payloads are around > 1MB. I am unable to figure this out. Is there any issue with approach? Glad if you can suggest alternative.blackode
Yes, I’m doing actual HTTP requests. I don’t have an example one to share. It is happening in live and I’m looking for suggestions like how can we achieve the decoding faster. My payloads are around > 1MB.
I am unable to figure this out. Is there any issue with my approach? Glad if you can suggest alternative.
Thanks
beepbeepbopbop
From
nimblepoolREADME in their Github:I assume you have a single worker pool as you’ve provided an atom name for this process.
blackode
@beepbeepbopbop thanks for prompt reply. I will create one per scheduler and will update you.
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.Asd
How are you making these HTTP requests? Do you have an example of your request, decode task loop?
dimitarvp
With a C/C++/Rust NIF anything below 50MB should be in the ballpark of milliseconds. Don’t optimise for a problem you don’t have. Just parse them in place and don’t worry about it.
Also you might be hitting a default timeout somewhere – in your original post.
saleyn
Take a look at glazer, which is several times more efficient at parsing large JSON payloads compared to Jason.