Earlier quoted context omitted.
> So e.g. you have to use Arc > In terms of C++ code that would equate to std::shared_ptr > which ... sounds quite wasteful in terms of scalability/performance. Why is it not possible to simply return a Rust promise? That's the way I do it in my C++ async (executor) library backed by work-stealing queues under the hood.
Not sure what you mean by "returning a rust promise". But yes, Arc > is a thread safe smart pointer containing a mutex, which has quite some overhead. You will see this in many places in the internals of async code that has to be Send. OK in many cases, but it can kill you if you have to go through this for many small operations.
Local async executors and why they should be the default
301–310 of 327 posts
Re: Local async executors and why they should be the default
#302Earlier quoted context omitted.
> So e.g. you have to use Arc > In terms of C++ code that would equate to std::shared_ptr > which ... sounds quite wasteful in terms of scalability/performance. Why is it not possible to simply return a Rust promise? That's the way I do it in my C++ async (executor) library backed by work-stealing queues under the hood.
> Why is it not possible to simply return a Rust promise? It… is? An Arc is what you need to share mutable data between “promises”.
Re: Local async executors and why they should be the default
#303Earlier quoted context omitted.
the use of async and await is a design decision that requires knowledge of the program's logic and desired behavior. It's not just a matter of compiler optimization, and that's why the compiler can't automatically figure out where to use these keywords. Suppose we have a service where users place orders, and we need to: 1. Save the order. 2. Deduct items from inventory. 3. Send a confirmation email. If we perform the…
You have it backward. The compiler should implicitly add the awaits for waitable objects, unless an operation is explicitly async. So you would write (in pseudocode): Task PlaceOrder(Order order) { SaveOrder(order); DeductItems(order); SendConfirmationEmail(order); } And the compiler will implicitly await all three operations (and ideally infer that your function is async). If you want to overlap computation, you avo…
Please don't misunderstand me; I'm not dismissing your proposal outright. However, it's essential to consider the potential trade-offs such as control flow management and error handling strategies. These are currently well-addressed by the async mechanism in C#.
Regarding polymorphic async-ness, I acknowledge this as a minor limitation within the current C# model. However, a common practice involves returning Task or Task, even when no async calls are involved. Moreover, I find Kotlin's approach to handling this through inlining of suspend functions quite intriguing. You can check it out here: https://kotlinlang.org/docs/kotlin-tips.html#the-suspend-and...
In closing, it would be beneficial to our discussion if we could clarify whether we're contemplating an optimization within the current C# framework or proposing a fundamentally different approach to asynchronicity.
Re: Local async executors and why they should be the default
#304It's a frustrating area. As I've mentioned before, I'm writing a high-performance metaverse client in Rust, something which has many of the problems of both a web browser and a MMO. If you want to have a good looking metaverse, it takes a gamer PC multiple CPUs and a good GPU to deal with the content flood. (This is why Meta's Horizon looks so bad.) Now you have to use all that hardware effectively. So what I'm writi…
I bought a 3600 in 2019, but a 7800x3D would blow it out of the water after just 4 years due to more cache, hitting 5Ghz, faster DDR5 RAM
https://youtu.be/B31PwSpClk8?t=800
shadow of the tomb raider, 152 FPS to 382 FPS
some games wouldn't double the FPS, but I'm really just looking to hit 280 FPS on my 280Hz monitor
Re: Local async executors and why they should be the default
#305Earlier quoted context omitted.
You have it backward. The compiler should implicitly add the awaits for waitable objects, unless an operation is explicitly async. So you would write (in pseudocode): Task PlaceOrder(Order order) { SaveOrder(order); DeductItems(order); SendConfirmationEmail(order); } And the compiler will implicitly await all three operations (and ideally infer that your function is async). If you want to overlap computation, you avo…
I appreciate the original comment by ikekkdcjkfke, and your elaboration, gpderetta. However, I perceive a distinction between compiler optimization and proposing a fundamentally different model for handling asynchronicity. It seems to me that what you're suggesting deviates significantly from the existing C# model. Transitioning to this model wouldn't be a simple matter of compiler optimization—it would be a major br…
I don't think that the async/sync division is a minor thing, but thanks for the Kotlin reference, I'll take a look. Before watching the video I guess that they implement 'stackfull-like' behaviour in otherwise stackless coroutines by force-inlining any HOF so that the coroutine is again flattened. If that's the case, that's great! What happens if inlining can't happen? They reject the code or convert to stackfull coroutines? That's for me as always been the holy grail: stackfull semantics that optimize to stackless (i.e. bounded stack usage) when possible (i.e. when the compler can see all possible yield points).
I have been trying to figure out (in C++) the subset of the language such as the optimization is always guaranteed (at the very least you need first class and explicit continuations so that the compiler can track them and inlining must be possible). Possibly Kotlin has cracked it.
Re: Local async executors and why they should be the default
#306Earlier quoted context omitted.
Where he notes that the .NET implementation wasn't without issues on Midori. Which is again another point of how the whole Rust's async/await process failed to learn from previous experiences. Even worse, because in what concerns .NET, the runtime is part of the story, while in Rust that is yet another piece of the puzzle that is in motion, not yet decided, although it can be anything as long it is tokio.
> Where he notes that the .NET implementation wasn't without issues on Midori. Indeed. In my opinion and experience async/await is a very leaky abstraction. I think it is definitely not worth it in most languages. Whether it is appropriate for rust I'm unconvinced. I think it is DOA in C++ with its required allocation, but I have yet to use it in anger.
See https://devblogs.microsoft.com/oldnewthing/20210504-01/?p=10...
Don't miss it.
Re: Local async executors and why they should be the default
#307Earlier quoted context omitted.
Sure it can, but all design patterns have their use cases. Generalizing and saying that one is just "terrible" (which your previous comment implied), and people "should learn" is just untrue and an ignorant take. Sometimes it's the only sane solution compared to others, considering project constraints.
Yes, that one is terrible compared to the alternatives. If there is one thing that really irritates me about the way we go about IT then it is that stuff that works and is reliable and well understood gets tossed and replaced by 'new shiny thing' which then eventually undergoes the same treatment. We are eternally stuck in reinventing wheels, rather than that we make real progress in for instance reliability and are…
Regarding Bjarne Stroustrup, he wasn't dragged anything, his C++ is described in "The C++ Annotated Referece Manual" and "The Design and Evolution of C++", everything that happened after that is responsability of WG21, where he only has one vote among 300+ persons.
There are several papers from him where he complains about the direction WG21 is going, like "Remember the Vasa".
Re: Local async executors and why they should be the default
#308Re: Local async executors and why they should be the default
#309Earlier quoted context omitted.
Go can do this because it’s closer to Java or C# than C. It has a runtime that gets compiled into every binary. Rust deliberately avoided that by design.
Indeed. That means that the interop story for golang is horrible. Golang can somewha work with libraries with C bindings. But you can not publish a golang lib as a lib.so with C bindings because of the runtime.
You can certainly publish lib.so with Go, here is an example,
https://www.ardanlabs.com/blog/2020/07/extending-python-with...
Re: Local async executors and why they should be the default
#310Earlier quoted context omitted.
> Why is it not possible to simply return a Rust promise? It… is? An Arc is what you need to share mutable data between “promises”.
I understand that part. What I don't understand is why https://docs.rs/promises/latest/promises/struct.Promise.html are not used instead.
The promise object you link to is not Clone, so there is no way for two different threads to refer to the same one without adding an intermediate `Arc`, and because all the methods on it operate by value that’s not exactly helpful either as you can’t move the promise out of the Arc.
Same with a tokio::task::Task. A JoinHandle can’t be duplicated (though according to its doc on some platforms it might be duplicatable — if the thread returned a duplicatable value anyway).