the idea is basically just use functions. no classes and very little statefulness
A better streams API is possible for JavaScript
91–100 of 167 posts
Re: A better streams API is possible for JavaScript
#92Earlier quoted context omitted.
No, you'll just need to (potentially) keep the last 1-2 bytes of the previous chunk after each iteration. Come on, restartable UTF-8 APIs has been around for more than 30 years.
But those code points were just inputs to another stream transformation that turns a stream of code points into a stream of graphemes. Rapidly your advice turns into "just do everything in one giant transformation" and that loses the benefits of streams, which are meant to be highly composable to create efficient, multi-step transformation pipelines.
Re: A better streams API is possible for JavaScript
#93There's a lot I like about this API, mainly the pull-based iterator approach. I don't really see what the value of the sync APIs are though. What's the difference of just using iterators directly for sync streams?
It avoids the overhead of Promises, so I can imagine that this would be quite useful if you know that blocking the thread is fine for a little while (e.g. in a worker).
Re: A better streams API is possible for JavaScript
#94Async iterables aren't necessarily a great solution either because of the exact same promise and stack switching overhead - it can be huge compared to sync iterables. If you're dealing with small objects at the production side, like individual tag names, attributes, bindings, etc. during SSR., the natural thing to do is to just write() each string. But then you see that performance is terrible compared to sync iterab…
I liked conartist6's proposal, type Stream = { next(): { done, value: T } | Promise } Where T=Uint8Array. Sync where possible, async where not. Engineers had a collective freak out panic back in 2013 over Do not unleash Zalgo , a worry about using callbacks with different activation patterns. Theres wisdom there, for callbacks especially; it's confusing if sometime the callback fires right away, sometimes is in fact…
I was so sick of being slapped around by LJHarb who claimed to me again and again that TC39 was honoring the Zalgo post (by slapping synthetic deferrals on everything) that I actually got Isaacs to join the forum and set him straight: https://es.discourse.group/t/for-await-of/2452/5
Re: A better streams API is possible for JavaScript
#95Re: A better streams API is possible for JavaScript
#96Earlier quoted context omitted.
But those code points were just inputs to another stream transformation that turns a stream of code points into a stream of graphemes. Rapidly your advice turns into "just do everything in one giant transformation" and that loses the benefits of streams, which are meant to be highly composable to create efficient, multi-step transformation pipelines.
No, it doesn't turn into this. Those two bytes of leftovers plus a flag are kept inside the stream generator that transforms bytes into code points, every time you pull it those two bytes are used as an initial accumulator in the fold that takes the chunk of bytes and yield chunk of code points and the updated accumulator. You don't need to inline it all into one giant transform. Come on, it's how (mature libraries o…
> If you want to stream arbitrary JavaScript values, use async iterables directly
OK, so we have to do this because code points are numbers larger than 8 bits, so they're arbitrary JS values and we have to use async iterables directly. This is where the amount of per-item overhead in an async iterable starts to strangle you because most of the actual work being done at that point is tearing down the call stack between each step of each iterator and then rebuilding it again so that the debugger has some kind of stack traces (if you're using for await of loops to consume the iterables that is).
Re: A better streams API is possible for JavaScript
#97Promises should not be a big overhead. If they are, that seems like a bug in JS engines. At a native level (C++/rust), a Promise is just a closure added to a list of callbacks for the event loop. Yes, if you did 1 per streamed byte then it would be huge but if you're doing 1 promise per megabyte, (1000 per gig), it really shouldn't add up 1% of perf.
So if you're going to flatten everything into one stream then you can't have a for loop implementation that defensively awaits on every step, or else it'll be slooooooooow. That's my proposal for the change to the language is a syntax like
for await? (value of stream) {
}
which would only do the expensive high-level await when the underlying protocol forced it to by returning a promise-valued step.Re: A better streams API is possible for JavaScript
#98We deserve a better language than JavaScript. Sadly it will never happen. WebAssembly failed to keep some of its promises here.
Re: A better streams API is possible for JavaScript
#99Earlier quoted context omitted.
UDP is a protocol, not an API
True. But it’s also true that trying to shoehorn every use case into TCP streams is counter productive. A stream API can layer over UDP as well (reading in order of arrival with packet level framing), but such a stream would a bit weird and incompatible with many stream consumers (e.g. [de]compression). A UDP API is simpler and more naturally event (packet) oriented. The concepts don’t mix well. Still, it would be ni…
Re: A better streams API is possible for JavaScript
#100Earlier quoted context omitted.
I liked conartist6's proposal, type Stream = { next(): { done, value: T } | Promise } Where T=Uint8Array. Sync where possible, async where not. Engineers had a collective freak out panic back in 2013 over Do not unleash Zalgo , a worry about using callbacks with different activation patterns. Theres wisdom there, for callbacks especially; it's confusing if sometime the callback fires right away, sometimes is in fact…
Yeah I think people took away "It's better to be uniform" since they were trying to block out the memory of much-feared Zalgo, but if you read the article carefully it says in big letters "Avoid Synthetic Deferrals" then goes on to advocate for patterns exactly like MaybeAsync to be used "if the result is usually available right now, and performance matters a lot". I was so sick of being slapped around by LJHarb who…
I feel like my deep dives into iterator performance are somewhat wasted because I might have made my project faster, but it's borderline dark magic and doesn't scale to the rest of the ecosystem because the language is broken.