Live data from Hacker News

Principles for Fast Tokio Applications

dial9-rs.github.io

21–30 of 72 posts

Re: Principles for Fast Tokio Applications

#21
post #4
post #2

One great use of agentic coding is being able to add and very granular tracing instrumentation to help with these sort of optimizations.

Also a great way to make sure that your app spends most of its time in observability overhead. For example even the latency histogram that the OP mentions is wildly expensive.

Was this in a specific application? I wouldn't necessarily expect that histogram to be particularly bad for most applications.

Re: Principles for Fast Tokio Applications

#22
post #16
post #14

Earlier quoted context omitted.

I'm just reporting from the trenches here. I think you are suggesting that everyone is aware of and capable of using state-of-the-art (from 20 years ago) tracing schemes like XRay[1], when in reality they are not. Most projects would be well-served by any basic profiler but even profiling is apparently for wizards, because I've seen a lot of projects that will resort to manually annotating functions with OTel trace s…

Not even an analog: https://doc.rust-lang.org/beta/unstable-book/compiler-flags/... It's worth pointing out though that just tracing function calls isn't good enough for the kinds of stackless coroutines that run in async Rust tasks. You need a way of mapping between the async tasks and the compiler emitted traces. afaik, C/C++ have the same problem.

The difference is nobody in the C++ community believes that a dominant asynchronous executor library exists, and there is not a pervasive belief that it would be helpful.

Re: Principles for Fast Tokio Applications

#24
post #21
post #4

Earlier quoted context omitted.

Also a great way to make sure that your app spends most of its time in observability overhead. For example even the latency histogram that the OP mentions is wildly expensive.

Was this in a specific application? I wouldn't necessarily expect that histogram to be particularly bad for most applications.

Reading the clock every time you jump into a closure is in fact incredibly wasteful, and is exacerbated by chopping work up into tiny chunks for questionable reasons.

Re: Principles for Fast Tokio Applications

#25
post #11
post #4

Earlier quoted context omitted.

Also a great way to make sure that your app spends most of its time in observability overhead. For example even the latency histogram that the OP mentions is wildly expensive.

Just curious, why? Is this true even if you did something like a per-CPU histogram that uses atomic ops to increment?

If you have a per-cpu metric there would not be a reason to use atomic instructions to mutate it.

Re: Principles for Fast Tokio Applications

#26
post #19

For a true high performance you should use thread busy-spinning, CPU pinning and SPSC/MPSC ring buffers.

It all depends on what you are doing. I do embedded with strict realtime requirements. CPU pinning would not be an option. I have also done software that should use as little resources as possible (but still be quick) to coexist with other software on the same hardware.

All of these are different, valid, meanings of high performance. You need context. An interactive IDE is yet another thing that needs to be high performance in yet another way.

Re: Principles for Fast Tokio Applications

#27
"Be careful with mutexes" is good advice, but I'm surprised it doesn't explicitly call out the various channels that tokio provides as alternatives (detailed here: https://docs.rs/tokio/latest/tokio/sync/index.html). There are a variety of options that fit different use cases, and you don't even need to enable the runtime feature to use them (e.g. if you want to do a single check for completion rather than await). I'd estimate that at least half of the bottlenecks I've seen with mutexes when using tokio could have been avoided by not even using a mutex at all and instead passing the data that's truly needed across different tasks with some type of channel.

The other trick I've used a few times that's a bit hacky but can get the job done is when reading a snapshot of the data under a mutex is enough without needing to prevent other changes; if that's the case, you can just clone the data and drop the mutex to allow other uses move forward at the cost of the data potentially being stale.

Re: Principles for Fast Tokio Applications

#28
post #15

When you're at a point of tuning Tokio, consider taking a look at ef_vi/DPDK + SPDK

I don't think there is a ton of overlap. tokio is appropriate for general userspace apps, ranging anywhere from a CLI, GUI, API or web app. DPDK and SPDK are specialized fast paths for building network data paths and storage solutions that come with tradeoffs: DPDK uses poll mode drivers, outside of the operating system, which have various implications including busy waiting and taking over the interface. That is why DPDK is fast, no kernel/userspace context switching and copies, and the drivers are tuned for the polling model. But it's not a general purpose building block.

Re: Principles for Fast Tokio Applications

#29
post #22
post #16

Earlier quoted context omitted.

Not even an analog: https://doc.rust-lang.org/beta/unstable-book/compiler-flags/... It's worth pointing out though that just tracing function calls isn't good enough for the kinds of stackless coroutines that run in async Rust tasks. You need a way of mapping between the async tasks and the compiler emitted traces. afaik, C/C++ have the same problem.

The difference is nobody in the C++ community believes that a dominant asynchronous executor library exists, and there is not a pervasive belief that it would be helpful.

The "C++ community", if it even exists, barely believes in sharing code let alone any library being "dominant." They'd have to agree on a build system first, after all.

But honestly that's a mischaracterization of the situation in Rust. Tokio is popular for networked service backends. If that's the wheelhouse you're in then yea it might look "dominant."

Post reply on HN