Live data from Hacker News

Principles for Fast Tokio Applications

dial9-rs.github.io

51–60 of 72 posts

Re: Principles for Fast Tokio Applications

#51
post #48
post #44

Earlier quoted context omitted.

In general your unpinned userspace threads will hit the same CPU 99.99% of the time, but not 100%.

Sure. You get the pointer, you lock the mutex, 99.99% of the time that is uncontended, then you set all the metrics and release it.

Taking the mutex uses (uncontended) atomic ops.

Re: Principles for Fast Tokio Applications

#52
post #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…

Tasks and channels is the way. You can get something that feels like programming a real preemptive concurrency model like BEAM languages or golang but with minimal overhead.

When you send a message in Erlang, nothing the recipient does with the message impacts anything on the sender side. That's good!

In principle, they could have used something like copy-on-write for this, but in practice they really just make a copy of the bytes.

Alas in Go, when you mutate what you received on a channel, you mutate the object the sender might still be holding. That's pretty annoying. It gets worse, because Golang has no way to declare something as `const` (like in C) nor that you are holding an immutable borrow (like in Rust). So you need to rely on conventions and perhaps a linter.

Slighty less of a tangent: task and channels and software transactional memory (STM) are all great. I see mutexes as more of an implementation detail that you can use to implement these higher level abstractions (but they aren't the only way).

Re: Principles for Fast Tokio Applications

#54
post #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…

I think channels deserve more emphasis here too, especially because they change the architecture rather than just swapping synchronization primitives

Re: Principles for Fast Tokio Applications

#55
post #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…

Tasks and channels is the way. You can get something that feels like programming a real preemptive concurrency model like BEAM languages or golang but with minimal overhead.

Give a task ownership of some state, communicate through channels and suddenly a lot of locking just disappears from the design

Re: Principles for Fast Tokio Applications

#56
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.

One legitimately great thing about LLMs is that it makes it feasible to add these kind of tracing instrumentations temporarily for profiling and then throw them away so they never reach source control let alone production.

Reaching source control is fine as long as there is a compile time flag to disable the whole thing, which tokio-tracing does

Re: Principles for Fast Tokio Applications

#58
When working on 20ms audio frames, Trusting MissedTickBehavior::Delay is not enough by itself. If you miss a tick, frames pile up. If you don't want that, you should drain all accumulated full frames on every single tick. Otherwise, a single missed tick can cause permanent latency.

Re: Principles for Fast Tokio Applications

#60
post #37
post #28

Earlier quoted context omitted.

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…

Fwiw with ef_vi you have full control over the event queue - you don't need to busy-spin it, you can choose whatever strategy you prefer. > tokio is appropriate for general userspace apps Yep, and for those I wouldn't recommend it. But tokio is also widely used in performance-critical infrastructure and web services. For those I'd say it can definitely be worth taking a second look at kernel bypass.

ef_vi is a solarflare proprietary feature which is now a support product, AMD moved on to Pensando. Once you move away from busy poll, you rapidly lost grounds to use DPDK. The PMD is a deliberate design to elide latency and lower interconnect taxes like PCIe traffic and cache/memory bandwidth by batching queue maintenance, that is the bargain made with a PMD. The field opens to OS native fast paths which have fewer downsides outside of that niche. Application developers are rarely concerned with this because it's far from where the bottleneck is for them.. a web service is rarely primarily a data mover, while a proxy is. Tokio has more in common with Golang than something like DPDK.
Post reply on HN