3 ms·
> If the async version is easy to use Having a sync interface would make it easy to use in sync code, yes. I feel that we are far from zero cost abstractions n
by fooyc 10y ago
> If the async version is easy to use
Having a sync interface would make it easy to use in sync code, yes. I feel that we are far from zero cost abstractions now, though.
> switch stacks
Is it because the stacks in green threads is smaller than what C would expect ?
An interesting approach taken by Go here is to avoid calling C as much as possible. They don't call the libc for system calls, for instance. This is also what allows them to switch the execution to an other goroutine just before the syscall.
- steveklabnik 10y ago> I feel that we are far from zero cost abstractions now, though. Why? > Is it because the stacks in green threads is smaller than what C would expect ? Yes. > An interesting approach taken by Go here is to avoid calling C as much as possible. Right, so this is a cost that they can pay. Rust cannot.
- fooyc 10y agoAbout the cost of calling an async function synchronously: You had a call to read(). Now you have a thread, an event loop, a pooling mechanism, and a synchronization with the thread. That's much more system calls and cpu cycles, for an synchronous async read()
- pimeys 10y agoWell no, if you don't explicitly run it in a thread pool?
- fooyc 10y agoCan you explain how you run an async function synchronously, and how it has no overhead compared to calling a synchronous implementation of the same function ?
- Rusky 10y agoAs far as the kernel-side implementation goes, IO is always asynchronous. The CPU is not involved in the actual movement of data between memory and the network interface. When you make a synchronous syscall, the kernel initiates the operation, saves the state of your thread, and starts another one. When the network interface is done, it signals the kernel, which then marks your thread as runnable and schedules it for execution. When you make an asynchronous syscall, the kernel initiates the operation but does not block your thread. This is usually done in the context of an event loop, which makes a synchronous syscall (like epoll_wait) when it runs out of tasks to run. Thus, converting a single async syscall to a sync one means two syscalls: initiate the operation, then wait for its result. The extra round trip between user and kernel mode is basically free in this case because you're blocking on IO, and any logic it implements has to happen in the synchronous case anyway.
- fooyc 10y agoYou are side-stepping the question by explaining how scheduling works. You can not say that there is NO overhead. Using async code in a synchronous fashion is not going to be as fast as using plain sync code. Look at the wait() function: https://github.com/alexcrichton/futures-rs/blob/master/src/future/mod.rs#L270-L274 https://github.com/alexcrichton/futures-rs/blob/master/src/f... All this code IS overhead that wouldn't exist if the code was synchronous in the first place.
- pimeys 10y agoWell, here's the actual wait method: https://github.com/alexcrichton/futures-rs/blob/master/src/future/mod.rs#L270-L274 https://github.com/alexcrichton/futures-rs/blob/master/src/f... Of course depending on your executor, the IO can be async or sync.
- fooyc 10y agoI can see a LOT of overhead here. Am I wrong ? Have you ever ran a benchmark of a wait(async_read()) compared to just sync_read() ?
- fooyc 10y agoAbout the cost of skipping the libc: Do you mean a human/development cost ? Other than that, what would rust lose for not using the libc for system calls ?
- dbaupp 10y agosteveklabnik was not saying that it costs Rust to avoid libc, he was saying that "calling C has high overhead" (i.e. the main underlying reason for avoiding libc) is not something Rust can do, given its goals. This also means there's not nearly as much reason to put the effort into reimplementing the libc abstractions on every platform.
- stymaar 10y ago> An interesting approach taken by Go here is to avoid calling C as much as possible. They don't call the libc for system calls, for instance. This is also what allows them to switch the execution to an other goroutine just before the syscall. Go and Rust don't have the same goals. Rust has been designed as a replacement fro C and C++, that can be progressively integrated in a existing code base (like Firefox's one, or librsvg's). Go is Google's replacement for Java and Python to build independent micro-services. Go does a great job in its niche, but won't work at all where Rust shines. They are different languages, meant for different use-cases and if people could stop comparing them every time one is mentioned, I think we've made a great step forward …
- flukus 10y ago> They are different languages, meant for different use-cases and if people could stop comparing them every time one is mentioned Are they really that different use cases? Only rust is aimed at systems programming, but it seems like it could fill the application programming role quite well, where it is competing with go.
- dbaupp 10y agoPeople are welcome to use Rust for applications programming, but systems programming is where Rust brings the most to the table (memory safety without a GC was barely thought possible), and where development focus is: trade-offs are made with systems problems in mind, not application problems. This is reflected in many APIs through-out the ecosystem, which give fine control but require a lot of manual explicitness. IO is no different.
- eridius 10y ago> Having a sync interface would make it easy to use in sync code, yes. I feel that we are far from zero cost abstractions now, though. Why do you say that? Taking an async zero-cost-abstraction API and calling wait() on it doesn't magically make it more expensive. It just blocks the current thread until the async operation is done. Said operation is just as fast and zero-cost as it was before.
- fooyc 10y agoYou had a call to read(). Now you have a thread, an event loop, a pooling mechanism, and a synchronization with the thread. That's much more system calls and cpu cycles.
- eridius 10y agoIf you're just talking about a call to read(), that would be modeled by a Future, not a tokio reactor.
- fooyc 10y agoCan you explain how you can make a blocking call to an async function without overhead ?
- eridius 10y agoIf you accept that using the async call in an asynchronous nature doesn't have overhead, then you can turn it into a synchronous call by saying something like `.wait()`.
- fooyc 10y ago> If you accept that using the async call in an asynchronous nature doesn't have overhead Obviously that's not the case. There is a lot of overhead.