newton-peixoto

newton-peixoto

Hello everyone I’m studying about http streams and I notice a big difference in performance when returning everything at once and when streaming and that made me think if streaming a big file is really worth it or if there is something wrong with my implementation (most likely that haha) So if anyone could help me understand this situation I’d appreciate a lot. Thanks

non-stream implementation

  get "/no-stream" do
    pokemons = File.read!("file.json")
    conn |> send_resp(200, pokemons)
  end

Stream implementation :

  get "/" do

    conn = conn
    |> put_resp_content_type("text/event-stream")
    |> put_resp_header("Access-Control-Allow-Origin", "*")
    |> send_chunked(200)

    File.stream!("file.json")
    |> Jaxon.Stream.from_enumerable
    |> Jaxon.Stream.query([:root, :all])
    |> Stream.map(fn element ->
     {:ok, pokemon}  = Jason.encode(element)
      conn |> chunk(pokemon <> "\n")
    end )
    |> Stream.run

    conn
  end

As you can see the stream implementation has a latency MUCH higher even though the memory peak is a little bit lower. The question here is trying to understand if this is normal or if I messed up somehow I understand if is not possible to achieve the same latency as File.read! but the difference here is so high that made me wonder if something if off

BTW: the lib used to run the load test is called hey

Showing Posts 1 to 4

D4no0

D4no0

Streaming is always slower than sending/processing the whole file at once. In this case I think the latency comes from the overhead of sending multiple http packets.

Usually you want to stream when the file can be very big, this will ensure that both the server will never run out of memory when loading the file in the memory and the client the same.

kwando

kwando

Looks like your streaming version does more work tbh, parsing and encoding JSON..

Also I believe send_file would be even faster :slight_smile:

newton-peixoto

newton-peixoto OP

changing the endpoint to

 File.stream!("file.json")
    |> Stream.map(fn line ->
      conn |> chunk(line)
    end )
    |> Stream.run

made the endpoint 99% response time to 3s way higher than the 0.3s from file.read! but as you mentioned faster than the current json encondig..

kip

kip

ex_cldr Core Team

When I think about when to stream I think of three cases:

  1. Time-to-first pixel is more important that absolute throughput. By streaming the user may be able to see something after the first chunk. In non-streaming the whole content has to arrive first. Very use case dependent.

  2. The content is being streamed from an external source (like S3) to Elixir and then transformed before sending to the HTTP client. In this case streaming may be more memory efficient and the stream-in/stream-out may manage the upstream latency and bandwidth better.

  3. The size of the content to be sent is non-trivial in terms of memory availability on the Elixir system. (as you’ve already pointed out).

I appreciate some of this may be more theoretical benefit rather than practical benefit so as always, testing and measuring is important.

— All posts loaded —

Where Next? Top

Trending in Questions Top

katta
I having some trouble figuring out if I have set myself too strict of standards for my production server. Currently I can handle 75% of r...
New
achenet
Hello, I’m trying to build a basic Phoenix web-app, and I’d like to use Tailwind. However, when I launch mix phx.server, I get an error...
New
kpanic
Hi everyone, I am toying with the idea of building a “match maker” for giving personal help to people that wants to start coding. I sta...
New
Cxx-mlr
I’m working on a small exercise involving update_in/3, and I came up with this solution: data = %{ name: "Periodic Table", category:...
New
ChrisAmelia
I’ve got trouble wrapping my head around the order in which functions are called in this snippet (from Phoenix’s authentication): toke...
New
dillonoconnor
Is there any way to avoid the Hologram compiler running when using iex? It seems like the front-end code could potentially be disregarded...
New
thiagogsr
** (ArgumentError) expected :max_attempts to be a positive integer, got: {:@, [line: 10, column: 19], [{:max_attempts, [line: 10, column:...
New

Other Trending Topics Top

GenericJam
Edit: 2026 May 15 - This post is archived. Mob is alive!! Main docs: mob v0.7.11 — Documentation A bit of explanation for the slightly c...
New
mudasobwa
I am happy to introduce the very α version of the new programming language compiled to BEAM. Welcome Cure. It has literally three kille...
New
garrison
Hobbes is a low-level distributed database for the Elixir programming language. Hobbes provides a simple, safe, and scalable storage lay...
New
budgie
A little off-topic, but I feel like people here have a good head on their shoulders. I used to be quite good at making software. Was luc...
New
KristerV
Hey. Is there anyone here who creates agents in their apps? Not talking about using agents, but creating them. I’m finding it pretty diff...
New
mcass19
ExRatatui lets you cook up rich terminal UIs in Elixir, powered by Rust’s ratatui via Rustler NIFs. Build interactive terminal applicatio...
New

We're in Beta

About us Mission Statement

Options

Thread Display Mode




Thread Preview

Skip Thread Previews