Live data from Hacker News

A better streams API is possible for JavaScript

blog.cloudflare.com

61–70 of 167 posts

Re: A better streams API is possible for JavaScript

#61

Earlier quoted context omitted.

Your idea is flatten the UInt8Array into the stream. While I understand the logic, that's a terrible idea. * The overhead is massive . Now every 1KiB turns into 1024 objects. And terrible locality. * Raw byte APIs...network, fs, etc fundamentally operate on byte arrays anyway. In the most respectful way possible...this idea would only be appealing to someone who's not used to optimizing systems for efficiency.

JS engines actually are optimized to make that usage pattern fast. Small, short-lived objects with known key ordering (monomorphism) are not a major cost in JS because the GC design is generational. The smallest, youngest generation of objects can be quickly collected with an incremental GC because the perf assumption is that most of the items in the youngest generation will be garbage. This allows collection to be o…

It's not blazingly fast, no, but it's not as much overhead as people think either when they're imagining what it would cost to do the same thing with malloc. TC39 knew all this when they picked { step, done } as the API for iteration and they still picked it, so I'm not really introducing new risk but rather trusting that they knew what they were doing when they designed string iterators.

At the moment the consensus seems to be that these language features haven't been worth investing much in optimizing because they aren't widely used in perf-critical pathways. So there's a chicken and egg problem, but one that gives me some hope that these APIs will actually get faster as their usage becomes more common and important, which it should if we adopt one of these proposed solutions to the current DevX problems

Re: A better streams API is possible for JavaScript

#62

Earlier quoted context omitted.

Your idea is flatten the UInt8Array into the stream. While I understand the logic, that's a terrible idea. * The overhead is massive . Now every 1KiB turns into 1024 objects. And terrible locality. * Raw byte APIs...network, fs, etc fundamentally operate on byte arrays anyway. In the most respectful way possible...this idea would only be appealing to someone who's not used to optimizing systems for efficiency.

JS engines actually are optimized to make that usage pattern fast. Small, short-lived objects with known key ordering (monomorphism) are not a major cost in JS because the GC design is generational. The smallest, youngest generation of objects can be quickly collected with an incremental GC because the perf assumption is that most of the items in the youngest generation will be garbage. This allows collection to be o…

What happens when I send an extremely high throughput of data and the scheduler decides to pause garbage collection due to there being too many interrupts to my process sending network events? (a common way network data is handed off to an application in many linux distros)

Are there any concerns that the extra array overhead will make the application even more vulnerable to out of memory errors while it holds off on GC to process the big stream (or multiple streams)?

I am mostly curious, maybe this is not a problem for JS engines, but I have sometimes seen GC get paused on high throughput systems in GoLang, C#, and Java, which causes a lot of headaches.

Re: A better streams API is possible for JavaScript

#63
post #37
post #22

Earlier quoted context omitted.

What was it specifically about the style that stood out as incongruous, or that hindered comprehension? What was it that made you stumble and start paying close attention to the style rather than to the message? I am looking at the two examples, and I can't see anything wrong with them, especially in the context of the article. They both employ the same rhetorical technique of antithesis, a juxtaposition of contrasti…

The problem is less with the style itself and more that it's strongly associated with low-effort content which is going to waste the readers time. It would be nice to be able to give everything the benefit of the doubt, but humans have finite time and LLMs have infinite capacity for producing trite or inaccurate drivel, so readers end up reflexively using LLM tells as a litmus test for (lack of) quality in order to c…

> You might say well, it's on the Cloudflare blog so it must have some merit

I would instead say that it is written by James Snell, who is one of the central figures in the Node community; and therefore it must have some merit.

Re: A better streams API is possible for JavaScript

#64
The practical pain with Web Streams in Node.js is that they feel like they were designed for the browser use case first and backported to the server. Any time I need to process large files or pipe data between services, I end up fighting with the API instead of just getting work done.

The async iterable approach makes so much more sense because it composes naturally with for-await-of and plays well with the rest of the async/await ecosystem. The current Web Streams API has this weird impedance mismatch where you end up wrapping everything in transform streams just to apply a simple operation.

Node's original stream implementation had problems too, but at least `.pipe()` was intuitive. You could chain operations and reason about backpressure without reading a spec. The Web Streams spec feels like it was written by the kind of person who thinks the solution to a complex problem is always more abstraction.

Re: A better streams API is possible for JavaScript

#65

As it happens i have an even better API than this article proposes! They propose just using an async iterator of UInt8Array. I almost like this idea, but it's not quite all the way there. They propose this: type Stream = { next(): Promise }> } I propose this, which I call a stream iterator! type Stream = { next(): { done, value: T } | Promise } Obviously I'm gonna be biased, but I'm pretty sure my version is also obj…

In the language I've been working on for a couple months, Eidos, streams are achieved through iterators as well. It's dead simple. And lazy for loops are iterators, and there is piping syntax. This means you can do this (REPL code):

  >> fn double(iter: $iterator) {
    return *for x in iter { $yield( x * 2 )}
  }

  >> fn add_ten(iter: $iterator) {
    return *for x in iter { $yield( x + 10 )}
  }

  >> fn print_all(iter: $iterator) {
    for x in iter { $print( x )}
  }

  >> const source = *for x in [1, 2, 3] { $yield( x )}

  >> source |> double |> add_ten |> print_all
  12
  14
  16
You get backpressure for free, and the compiler can make intelligent decisions, such as automatic inlining, unrolling, kernel fusing, etc. depending on the type of iterators you're working with.

Re: A better streams API is possible for JavaScript

#67

Earlier quoted context omitted.

> Obviously I'm gonna be biased, but I'm pretty sure my version is also objectively superior: > - I can easily make mine from theirs That... doesn't make it superior? On the contrary, theirs can't be easily made out of yours, except by either returning trivial 1-byte chunks, or by arbitrary buffering. So their proposal is a superior primitive. On the whole, I/O-oriented iterators probably should return chunks of T, o…

As an abstraction I would say it does make mine superior that it captures everything theirs can and more that theirs can't. Plus theirs involves the very concrete definition of an array, which might have 100 prototype methods in JS, each part of their API surface. I have one function in my API surface.

[deleted]

Re: A better streams API is possible for JavaScript

#68

[flagged]

> high-performance data processing tools in JS I may be naive in asking this, but what leads someone to building high perf data tools in JS? JS doesn't seem to me like it would be the tool of choice for such things

Browsers are now able to stream files from disk so you can create a high performance tool that'll read locally, do [x] with it and present the results, all without any network overhead.

Re: A better streams API is possible for JavaScript

#69

The practical pain with Web Streams in Node.js is that they feel like they were designed for the browser use case first and backported to the server. Any time I need to process large files or pipe data between services, I end up fighting with the API instead of just getting work done. The async iterable approach makes so much more sense because it composes naturally with for-await-of and plays well with the rest of t…

It's news to me that anyone actually uses the web streams in node. I thought they were just for interoperability, for code that needs to run on both client and server.

Re: A better streams API is possible for JavaScript

#70
post #33

Earlier quoted context omitted.

There is no such thing as Uint8Array . Uint8Array is a primitive for a bunch of bytes, because that is what data is in a stream. Adding types on top of that isn't a protocol concern but an application-level one.

> Adding types on top of that isn't a protocol concern but an application-level one. I agree with this. I have had to handle raw byte streams at lower levels for a lot of use-cases (usually optimization, or when developing libs for special purposes). It is quite helpful to have the choice of how I handle the raw chunks of data that get queued up and out of the network layer to my application. Maybe this is because I…

My concern isn't with how you write your network layer. Use buffers in there, of course.

But what if you just want to do a simple decoding transform to get a stream of Unicode code points from a steam of bytes? If your definition of a stream is that it has UInt8 values, that simply isn't possible. And there's still gonna be waaay too many code points to fall back to an async iterator of code points.

Post reply on HN