Live data from Hacker News

Show HN: Async UI: A Rust UI Library Where Everything is a Future

wishawa.github.io

81–90 of 96 posts

Re: Show HN: Async UI: A Rust UI Library Where Everything is a Future

#81
post #75

It's 2.56 MB gzip!

The Todo example is 2.5 MB non -gzipped. About 600KB gzipped. Still large, but it's because we're shipping a lot of code that we don't need. Mostly the APIs exposed by web_sys. Proper dead code elimination would bring it down a lot.

Right. I'm interested in wasm lately and binary size is always my concern. There's almost non-existence of ast to wasm knowledge, only through Rust, C++, and some other langs.

If we really want a lot of non-javascript langs to succeed, I think we need to focus on raw wasm, .wat is pretty good for teaching. But they have new thing coming up which is called "Component Model", something about interface types related, which may help reducing bloat binaries.

Re: Show HN: Async UI: A Rust UI Library Where Everything is a Future

#82
post #27

Earlier quoted context omitted.

Java GUIs are horribly slow. Maybe it's not inherent but I've never encountered one that wasn't. C# ones are sometimes alright but only if they're using the native Windows frameworks.

Like IntelliJ?

Yes, exactly

Re: Show HN: Async UI: A Rust UI Library Where Everything is a Future

#83

Earlier quoted context omitted.

And why no just "classical" OS threads? Yeah, that's rhetoric, sure you can (or did you mean that with virtual one's?) And actually once upon a time, one of rust's selling point that you could do that safely without the common data races that you have to care for in the usual multithreading/multiprocessing environments, awesome! So to your grandposter..: > The point of async APIs is not speed boost, it's decoupling p…

> And why no just "classical" OS threads? Because of memory footprint and thread contention. OS thread's default stack size is often in the order of megabytes. On a server with 64GB of ram, that means you can't run more than ~64000 threads at once. That's not really a high number in the context of modern highly-concurrent servers. Meanwhile, goroutine's (and probably green thread's and virtual thread's from languages…

> you can't run more than ~64000 threads

Please, we started here with a GUI framework and how someone said async is not about performance - in the end you underline my point? I said it was motivated by massively concurrent use cases that require a high number of threads... (and that similarly motivates green threads et al, full agree).

Re: Show HN: Async UI: A Rust UI Library Where Everything is a Future

#84

I always dreamt of a GUI library where every widget would be a separate actor sending and receiving messages.

This is basically how Objective-C worked, being based on Smalltalk. Especially with NSNotificationCenter, you also get the async aspect (so-called “NSNotificationCenter spaghetti code”). Personally I have mixed feelings on it. ObjC/AppKit was clearly a step up from classic object UI toolkits built in rigid languages like C++, but I find React and its immediate-mode brethren far more enjoyable to work with precisely b…

I see. Isn't it (non-blocking message-exchanging objects) the most natural way to reason about though? Surely classic types and sequential function execution is more convenient for data processing/scripting but a GUI seems a naturally object-oriented thing and it feels better when the objects act independently.

Re: Show HN: Async UI: A Rust UI Library Where Everything is a Future

#85
post #78
post #32

Could you compare it with Sycamore with a few bullet points? I feel like it is pretty close even though you don't see the async exposed? L

Sycamore works pretty similarly to React. See https://www.reddit.com/r/rust/comments/xvv49w/comment/ir6pw0... for how Async UI is different from React-style frameworks.

It don't see how this works out. React uses a virtual Dom.

Sycamore:

> Write code that feels natural. Everything is built on reactive primitives without a cumbersome virtual DOM.

Yew works more similar to React

Re: Show HN: Async UI: A Rust UI Library Where Everything is a Future

#86

Earlier quoted context omitted.

What state does a userspace thread have to capture in order to work that a coroutine doesn't?

A userspace thread captures full a stack context, a delimited continuation used in async programming captures only the referenced variables needed for the remaining computation. This is a strict subset of the userspace thread state. For instance: fn f() { var v1 = ..., var v2 = ...; g(v2); } fn g(v2) { await; /* do something with v2 */ } // await is a context switch A userspace thread captures v1 and v2, an async com…

I don't understand your example. What is resumed after the await in f?

Generally stackfull continuations can capture more than stackless, but do not have to. If the context switch in f resumes into g, then only v2 needs to be captured.

If it resumes in an (indirect) caller of f then v1 will have to be captured if still live, but then again, this is not expressible at all with stackless coroutines, without explicitly or implicitly suspending all immediate callers (which would end up capturing v1 anyway).

That is, a stackful continuation equivalent to a stackless one only need to capture the same amount of state.

Also I don't think that defining as delimited the async continuations as opposed to the stackful ones is correct. You can have stackful delimited continuations.

Re: Show HN: Async UI: A Rust UI Library Where Everything is a Future

#87

Earlier quoted context omitted.

> And why no just "classical" OS threads? Because of memory footprint and thread contention. OS thread's default stack size is often in the order of megabytes. On a server with 64GB of ram, that means you can't run more than ~64000 threads at once. That's not really a high number in the context of modern highly-concurrent servers. Meanwhile, goroutine's (and probably green thread's and virtual thread's from languages…

> you can't run more than ~64000 threads Please, we started here with a GUI framework and how someone said async is not about performance - in the end you underline my point? I said it was motivated by massively concurrent use cases that require a high number of threads... (and that similarly motivates green threads et al, full agree).

You asked a question, I answered it.

Moreover, the last paragraph of my post actually agrees with you.

There is absolutely no need for a confrontational attitude.

Re: Show HN: Async UI: A Rust UI Library Where Everything is a Future

#88

Earlier quoted context omitted.

A userspace thread captures full a stack context, a delimited continuation used in async programming captures only the referenced variables needed for the remaining computation. This is a strict subset of the userspace thread state. For instance: fn f() { var v1 = ..., var v2 = ...; g(v2); } fn g(v2) { await; /* do something with v2 */ } // await is a context switch A userspace thread captures v1 and v2, an async com…

I don't understand your example. What is resumed after the await in f? Generally stackfull continuations can capture more than stackless, but do not have to. If the context switch in f resumes into g, then only v2 needs to be captured. If it resumes in an (indirect) caller of f then v1 will have to be captured if still live, but then again, this is not expressible at all with stackless coroutines, without explicitly…

> That is, a stackful continuation equivalent to a stackless one only need to capture the same amount of state.

Of course if they're equivalent, then they're equivalent. That's simply not the case with goroutines vs. async functions in existing system where the program is written in a sort of continuation-passing style and so the captured state is more explicit.

Of course you could also perform some sophisticated transform a goroutine program into this form as well and, with a suitable static analysis, also shrink the captured state in this fashion. However, the fact is that no existing system works like this, and so what I wrote previously is an accurate description of the tradeoffs at this time.

Re: Show HN: Async UI: A Rust UI Library Where Everything is a Future

#89

Earlier quoted context omitted.

I don't understand your example. What is resumed after the await in f? Generally stackfull continuations can capture more than stackless, but do not have to. If the context switch in f resumes into g, then only v2 needs to be captured. If it resumes in an (indirect) caller of f then v1 will have to be captured if still live, but then again, this is not expressible at all with stackless coroutines, without explicitly…

> That is, a stackful continuation equivalent to a stackless one only need to capture the same amount of state. Of course if they're equivalent, then they're equivalent. That's simply not the case with goroutines vs. async functions in existing system where the program is written in a sort of continuation-passing style and so the captured state is more explicit. Of course you could also perform some sophisticated tra…

So, you didn't give the explanation of what your snippet is supposed to do but, assuming that await returns control to f (as that the only thing that can happen with stackless coroutines) the equivalent in go would be to spawn a goroutine when calling g (pseudocode as I know approximately zero go):

   fn f() { var v1 = ..., var v2 = ...; go g(v2); }
   fn g(v2) { /* do something with v2 */ }  
There is no await as they are implicit in go. The coroutine spawned in f will only need to capture v2. I could make similar examples in cilk++, lua, or really any language with stackful coroutines.

Of course if you do not spawn a coroutine in f and it is instead part of another coroutine, v1 might be captured (unless the compiler identifies it as dead and reuses the stack slot, say, for v2). But to express the same with stackless coroutines you need to make f also a coroutine which will end up capturing v1 if live across the call.

Am I missing something?

Re: Show HN: Async UI: A Rust UI Library Where Everything is a Future

#90

Earlier quoted context omitted.

> That is, a stackful continuation equivalent to a stackless one only need to capture the same amount of state. Of course if they're equivalent, then they're equivalent. That's simply not the case with goroutines vs. async functions in existing system where the program is written in a sort of continuation-passing style and so the captured state is more explicit. Of course you could also perform some sophisticated tra…

So, you didn't give the explanation of what your snippet is supposed to do but, assuming that await returns control to f (as that the only thing that can happen with stackless coroutines) the equivalent in go would be to spawn a goroutine when calling g (pseudocode as I know approximately zero go): fn f() { var v1 = ..., var v2 = ...; go g(v2); } fn g(v2) { /* do something with v2 */ } There is no await as they are i…

> So, you didn't give the explanation of what your snippet is supposed to do but, assuming that await returns control to f

No, await is a context switch of some kind. In a stackful implementation the stack is switched to another thread at that point (say for an I/O wait), in an async implementation, the point after await is resumed with the live variables needed for the remainder of the program because it will be passed an explicit continuation.

> Of course if you do not spawn a coroutine in f and it is instead part of another coroutine, v1 might be captured (unless the compiler identifies it as dead and reuses the stack slot, say, for v2). But to express the same with stackless coroutines you need to make f also a coroutine which will end up capturing v1 if live across the call.

Yes, the idea is that v1 is not live, and existing stackful implementations will capture it regardless, where an async written program written in CPS form will not capture it. As I initially said the state captured by the latter is a strict subset of the former.

Post reply on HN