Earlier quoted context omitted.
We have some pretty vanilla file upload code that needs async. S3 latency is fairly high. If you're uploading a few tiny files per user per second, thread usage gets out of hand real fast. With a simulated load of ~20 users we were running over 1000 threads. Several posts in the chain say that 20k+ threads is "fine". Not unless you have a ton of cores. The memory and context switching overhead is gigantic. Eventually…
In what language?
Async-std: an async port of the Rust standard library
221–230 of 238 posts
Re: Async-std: an async port of the Rust standard library
#222Earlier quoted context omitted.
In Go you need to manually tell the runtime to spawn a goroutine with the `go` keyword, which also «litter» the code…
Except in practice, go keyword is used much more coarsly and sparingly because you can group all the block of function calls under one big go call. With async, every single function has to be flagged as beeing asynchronous and be called differently ( although maybe some modern languages have a way to group all the await calls ?)
Re: Async-std: an async port of the Rust standard library
#223Earlier quoted context omitted.
Many systems have been developed in systems enabled GC languages. C++11 introduced a GC API in the standard library, and one of the biggest C++ game engine does use GC in their engine objects, Unreal. C++ on Windows makes heavy use of reference counting (which is a GC algorithm from CS point of view), via COM/UWP. The biggest problem to overcome is religious, not technical.
>C++ on Windows makes heavy use of reference counting (which is a GC algorithm from CS point of view), via COM/UWP. Not sure if Ref counting is a good example here, as there is no runtime monitoring the object graph hierarchy and of course Rust it’s self uses ref counting in many situations.
Reference Counting is a garbage collection implementation algorithm from CS point of view.
RC has plenty of runtime costs as well, cache invalidation, lock contention on reference counters, stop the world in complex data structures, possible stack overflows if destructors are incorrectly written, memory fragmentation.
Re: Async-std: an async port of the Rust standard library
#224Earlier quoted context omitted.
In cooperative multitasking you can program when to give up control, not when it is regained. The regaining part is unpredictable. Which introduces a lot of non-determinism to deal with and overhead.
This is no different than async/await. At some point you await a scheduled primitive, it could be a timer, io readiness, an io completion... and yield to a scheduler. You don’t specify explicitly when you return. These are not tightly coupled coroutines. This is precisely what is going on in cooperative multitasking. I don’t see how this increases overhead to deal with either. Basically, coop multitasking and async/a…
[1] If implemented with care, not doing syscalls in the middle of async primitives and using fast nearly-O(1) algorithms for timers, etc. it can be incredibly fast. And of course Rust also gives enough room to mess up all that nice determinism.
Re: Async-std: an async port of the Rust standard library
#225I must be dumb, because every time I dive into async/await, I feel like I reach an epiphany about how it works, and how to use it. Then a week later I read about it again and totally lost all understanding. What do I gain if I have code like this [0], which has a bunch of `.await?` in sequence? I know .await != join_thread(), but doesn't execution of the current scope of code halt while it waits for the future we are…
User space threads and corouting is pretty much the right abstraction for application code. Async can be useful when more control over the details of execution is needed.
I've seen a lot of people try to manage complex programs by working with threads directly. Whatever they come up with is very unlikely to be as correct and reliable as the abstractions provided by the language. Even when they get it right, programs written with those techniques are difficult to modify without introducing new bugs.
Manual management of threads is becoming like manual management of memory -- it is discouraged by newer language features and you should only do if you really need to.
Re: Async-std: an async port of the Rust standard library
#226Earlier quoted context omitted.
Except in practice, go keyword is used much more coarsly and sparingly because you can group all the block of function calls under one big go call. With async, every single function has to be flagged as beeing asynchronous and be called differently ( although maybe some modern languages have a way to group all the await calls ?)
That's funny how gophers can at the same time defend the «explicitness» of the if-based error handling, and be annoyed to have syntactic annotations for the yield points for coroutines (because that's exactly what `await` is, versus the yield points silently added by the go compiler everywhere so the runtime can perform its scheduling).
Re: Async-std: an async port of the Rust standard library
#227Earlier quoted context omitted.
Are those really the only options? I'm trying to wrap my head around how using a fixed size thread pool for I/O automatically implies deadlocks but I just can't. Unless the threads block on completion until their results are consumed instead of just notifying and then taking the next task.. I can definitely imagine blocking happening while waiting for a worker to be available, though. Did you mean simply blocking ins…
N threads, with N readers waiting for a message that will only come if the N+1 reader (still in the queue) gets a message first.
The same scenarios would lead to resource exhaustion if the thread pool wasn't bounded.
Re: Async-std: an async port of the Rust standard library
#228Earlier quoted context omitted.
I'm sitting in a Rust talk at a conference right now, and the speaker has slides comparing the syntax to Ruby/TypeScript/Python. "You already basically know Rust" A lot of the fancier stuff is very different, but there's fairly close parallels to most of the basic syntax.
Basically everything Algol-descended has close parallels in the syntax. That falls apart as soon as you hit a turbofish. I'm not saying the language or even the syntax is bad, but I think it does earn its reputation for being a little hard to read.
Re: Async-std: an async port of the Rust standard library
#229Earlier quoted context omitted.
Nobody is denying that async code is faster. But it’s not as dramatic as presented in the grand parent post. And IMHO the added code complexity is not worth the trouble.
> And IMHO the added code complexity is not worth the trouble. The thing is, this is just that - your opinion, generalized as The Truth. But engineering is about making the right trade-offs. Often threading will be fine, you'll win simplicity, and all is good. But sometimes you really need the performance, or your field is crowded and its a competitive advantage. Think large-scale infrastructure at AWS, central load-…
Heh? Where?
Re: Async-std: an async port of the Rust standard library
#230Earlier quoted context omitted.
As an aside, Zig[0] recently merged a change to try and tackle the use case of [a]sync-agnostic functions: https://github.com/ziglang/zig/issues/1778 . The "What Color is Your Function" blog post appears to have been one of the inspirations behind the change. Some of Andy's (the language creator) recent videos go over it in detail: https://www.youtube.com/channel/UCUICU6mgcyGy61pojwuWyHA [0]: https://ziglang.org
That looks quite interesting! The idea is that you can set the global "io_mode" mode to blocking, mixed or evented and I/O functions will switch their implementation accordingly. The type of the function will then, if I got that right, propagate up the call stack and turn functions that touch it transparently into either normal or async/awaitable funtions. Nice way to avoid a bifurcation of the ecosystem into red/gre…
I mean, don’t you know at compile-time whether you want something to be async or not? If so, it should be handled by the type system, not by mutating a variable at runtime.