<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Runtime on</title><link>/tags/runtime/</link><description>Recent content in Runtime on</description><generator>Hugo</generator><language>en</language><lastBuildDate>Thu, 02 Oct 2025 16:55:31 +0000</lastBuildDate><atom:link href="/tags/runtime/index.xml" rel="self" type="application/rss+xml"/><item><title>Lesson 8: Runtime Comparison — Tokio vs async-std vs smol vs glommio</title><link>/post/rust/rust-runtime-comparison/</link><pubDate>Thu, 02 Oct 2025 16:55:31 +0000</pubDate><guid>/post/rust/rust-runtime-comparison/</guid><description>&lt;p&gt;Every few months, someone asks me &amp;ldquo;which async runtime should I use?&amp;rdquo; and every time my answer is frustrating: &amp;ldquo;it depends.&amp;rdquo; But after spending the last seven lessons understanding how runtimes work from the inside, we can finally have a real conversation about what the differences actually are, why they exist, and when each one is the right choice.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;ve used all four of these runtimes in production. Tokio for most things, smol for a lightweight embedded project, glommio for a storage engine prototype, and async-std briefly before migrating away from it. Let me share what I&amp;rsquo;ve learned — not from reading documentation, but from debugging real problems at 2 AM.&lt;/p&gt;</description></item><item><title>Lesson 7: Designing a Custom Async Runtime — When Tokio isn't enough</title><link>/post/rust/rust-runtime-custom-runtime/</link><pubDate>Tue, 30 Sep 2025 11:20:06 +0000</pubDate><guid>/post/rust/rust-runtime-custom-runtime/</guid><description>&lt;p&gt;A colleague once asked me, &amp;ldquo;Why would anyone build a custom async runtime when Tokio exists?&amp;rdquo; Fair question. Tokio is battle-tested, well-maintained, and fast. For 95% of use cases, it&amp;rsquo;s the right answer. But I&amp;rsquo;ve now been in three situations where it wasn&amp;rsquo;t — and each one taught me something about what a runtime actually does.&lt;/p&gt;
&lt;p&gt;The first was a latency-sensitive trading system where work-stealing&amp;rsquo;s cache invalidation was unacceptable. The second was an embedded system with no allocator. The third was a specialized database engine where we needed precise control over I/O scheduling. Each time, understanding how to build a runtime from the ground up saved the project.&lt;/p&gt;</description></item><item><title>Lesson 6: Work-Stealing Schedulers — Balancing load across cores</title><link>/post/rust/rust-runtime-work-stealing/</link><pubDate>Sat, 27 Sep 2025 13:45:50 +0000</pubDate><guid>/post/rust/rust-runtime-work-stealing/</guid><description>&lt;p&gt;I once spent two days debugging a performance issue where our Tokio application was using four cores but only one was doing any work. Three threads were idle, one was pegged at 100%. The problem wasn&amp;rsquo;t Tokio&amp;rsquo;s scheduler — it was ours. We&amp;rsquo;d accidentally created a pattern where all tasks were spawned from and waking on the same thread, and nothing triggered work-stealing because the tasks completed too quickly.&lt;/p&gt;
&lt;p&gt;That experience taught me that you can&amp;rsquo;t treat the scheduler as a black box. If you understand how work-stealing works, you can design your task topology to take advantage of it. If you don&amp;rsquo;t, you&amp;rsquo;ll write code that accidentally defeats it.&lt;/p&gt;</description></item><item><title>Lesson 5: The Reactor Pattern — How Tokio actually works</title><link>/post/rust/rust-runtime-reactor-pattern/</link><pubDate>Wed, 24 Sep 2025 09:27:13 +0000</pubDate><guid>/post/rust/rust-runtime-reactor-pattern/</guid><description>&lt;p&gt;I read the Tokio source code on a Sunday afternoon, expecting to find something inscrutable. Layers of unsafe code, impenetrable abstractions, the kind of thing that makes you question your career choices. What I actually found was a clean, well-documented reactor implementation that I could follow. Not easily — but followably. The architecture is elegant once you see how the pieces connect.&lt;/p&gt;
&lt;p&gt;This lesson is about that architecture. Not Tokio&amp;rsquo;s API — you already know how to use &lt;code&gt;tokio::spawn&lt;/code&gt; and &lt;code&gt;TcpStream&lt;/code&gt;. This is about what happens &lt;em&gt;underneath&lt;/em&gt; when you call those functions. The reactor pattern, the I/O driver, the timer wheel, and how they all feed into the executor.&lt;/p&gt;</description></item><item><title>Lesson 4: epoll/kqueue — Platform event loops</title><link>/post/rust/rust-runtime-epoll-kqueue/</link><pubDate>Sun, 21 Sep 2025 17:08:45 +0000</pubDate><guid>/post/rust/rust-runtime-epoll-kqueue/</guid><description>&lt;p&gt;Before I understood event loops, I thought async I/O was some kind of kernel magic. You register interest in a socket, and somehow the OS tells you when data arrives — without blocking a thread. How? I imagined complex kernel subsystems doing heavy lifting behind the scenes.&lt;/p&gt;
&lt;p&gt;Turns out, the mechanism is almost embarrassingly simple. The kernel maintains a list of file descriptors you care about. When something happens on one of them, it flips a bit. You ask &amp;ldquo;what happened?&amp;rdquo;, it tells you. That&amp;rsquo;s it. The entire async I/O ecosystem — Tokio, Node.js, nginx, everything — is built on this one primitive.&lt;/p&gt;</description></item><item><title>Lesson 3: io_uring — Zero-copy async I/O on Linux</title><link>/post/rust/rust-runtime-io-uring/</link><pubDate>Fri, 19 Sep 2025 10:33:08 +0000</pubDate><guid>/post/rust/rust-runtime-io-uring/</guid><description>&lt;p&gt;I ran a benchmark last year that genuinely surprised me. A simple TCP echo server using &lt;code&gt;io_uring&lt;/code&gt; was handling 40% more connections per second than the same server on &lt;code&gt;epoll&lt;/code&gt;, with measurably lower tail latencies. Not 5% — forty percent. On the same hardware, same kernel version, same application logic. That&amp;rsquo;s when I stopped treating &lt;code&gt;io_uring&lt;/code&gt; as a curiosity and started treating it as the future of Linux I/O.&lt;/p&gt;
&lt;p&gt;If you&amp;rsquo;ve been building async runtimes on &lt;code&gt;epoll&lt;/code&gt; (or even &lt;code&gt;kqueue&lt;/code&gt; on macOS), &lt;code&gt;io_uring&lt;/code&gt; changes the game completely. Let me show you why.&lt;/p&gt;</description></item><item><title>Lesson 2: Building a Minimal Executor — Your own async runtime</title><link>/post/rust/rust-runtime-executor/</link><pubDate>Wed, 17 Sep 2025 14:12:37 +0000</pubDate><guid>/post/rust/rust-runtime-executor/</guid><description>&lt;p&gt;The moment I built my first executor from scratch, async Rust stopped being scary. Not because executors are simple — they&amp;rsquo;re not — but because once you see the machinery, every &amp;ldquo;mysterious&amp;rdquo; behavior has an obvious explanation. Futures hanging? The waker isn&amp;rsquo;t being called. Tasks not making progress? The executor&amp;rsquo;s run loop has a bug. Performance terrible? You&amp;rsquo;re probably polling too aggressively or not enough.&lt;/p&gt;
&lt;p&gt;So let&amp;rsquo;s build one. A real, working executor. Not a production-quality one (that&amp;rsquo;s Tokio&amp;rsquo;s job), but one that actually runs futures to completion, handles multiple tasks, and demonstrates every concept from the previous lesson.&lt;/p&gt;</description></item><item><title>Lesson 1: Future Internals — Poll, Waker, Context</title><link>/post/rust/rust-runtime-future-internals/</link><pubDate>Mon, 15 Sep 2025 08:45:22 +0000</pubDate><guid>/post/rust/rust-runtime-future-internals/</guid><description>&lt;p&gt;I thought I understood Rust futures until I tried to implement one without &lt;code&gt;async&lt;/code&gt;/&lt;code&gt;await&lt;/code&gt;. Not a toy future that immediately returns &lt;code&gt;Ready&lt;/code&gt;. A real future — one that yields, gets woken up, and resumes where it left off. That exercise broke every mental model I had and rebuilt it from scratch.&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;async&lt;/code&gt;/&lt;code&gt;await&lt;/code&gt; syntax is one of Rust&amp;rsquo;s great lies. It looks simple. It &lt;em&gt;feels&lt;/em&gt; like you&amp;rsquo;re writing sequential code. Under the hood, the compiler is generating state machines, threading waker references through call graphs, and constructing self-referential structs that would make most C++ programmers nervous. Let&amp;rsquo;s rip the lid off.&lt;/p&gt;</description></item></channel></rss>