<story><title>Tokio internals: Understanding Rust&apos;s async I/O framework</title><url>https://cafbit.com/post/tokio_internals/</url></story><parent_chain><item><author>kindfellow92</author><text>&amp;gt; Unfortunately, Tokio is notoriously difficult to learn due to its sophisticated abstractions.&lt;p&gt;Aren’t abstractions supposed to make things easier to learn? Something about the idea of “complex abstractions” seems wrong.&lt;p&gt;(Edit: this is not a criticism of Tokio, it’s a criticism of the OP’s characterization of “sophisticated abstractions” which IMO should reduce complexity)</text></item></parent_chain><comment><author>jcrites</author><text>&amp;gt; Aren’t abstractions supposed to make things easier to learn?&lt;p&gt;Not always. Some abstractions are designed to make it easier to solve hard problems correctly (than without the abstraction).&lt;p&gt;For example, consider Rust&amp;#x27;s memory model. Many people criticize that model as difficult to learn. By comparison, you might argue that C&amp;#x27;s memory model is simpler to learn. Yet, the C approach to allocating, using, and freeing memory is highly error-prone. C programs historically have frequently had mistakes such as use-after-free errors, or buffer under&amp;#x2F;overflow&amp;#x2F;reuse errors. The high-profile OpenSSL Heartbleed vulnerability was an example of a weakness in C&amp;#x27;s memory model and memory handling abstractions [1].&lt;p&gt;Rust&amp;#x27;s memory model may be more difficult to learn than C&amp;#x27;s, but once learned, they are abstractions that provide an advantage in building correct software, by ruling out certain classes of mistakes. (GC in languages like C# and Java and Go can also prevent these mistakes, but comes with a runtime cost. Rust aims to provide zero-cost abstractions.)&lt;p&gt;Building correct async IO programs using kernel abstractions is difficult for similar reasons as it&amp;#x27;s difficult to write correct programs with C&amp;#x27;s memory model. It&amp;#x27;s especially difficult if you want the async IO program to be portable across multiple OS&amp;#x2F;kernels. I have not used Tokio, but I would guess that its Rust-powered abstractions will make it difficult or impossible to leak memory or sockets, or to fail to handle error cases that might arise handling async IO.&lt;p&gt;[1] &lt;a href=&quot;https:&amp;#x2F;&amp;#x2F;www.seancassidy.me&amp;#x2F;diagnosis-of-the-openssl-heartbleed-bug.html&quot; rel=&quot;nofollow&quot;&gt;https:&amp;#x2F;&amp;#x2F;www.seancassidy.me&amp;#x2F;diagnosis-of-the-openssl-heartble...&lt;/a&gt;</text></comment>
<story><title>Tokio internals: Understanding Rust&apos;s async I/O framework</title><url>https://cafbit.com/post/tokio_internals/</url></story><parent_chain><item><author>kindfellow92</author><text>&amp;gt; Unfortunately, Tokio is notoriously difficult to learn due to its sophisticated abstractions.&lt;p&gt;Aren’t abstractions supposed to make things easier to learn? Something about the idea of “complex abstractions” seems wrong.&lt;p&gt;(Edit: this is not a criticism of Tokio, it’s a criticism of the OP’s characterization of “sophisticated abstractions” which IMO should reduce complexity)</text></item></parent_chain><comment><author>tatterdemalion</author><text>There are various criticisms of tokio, coming from different directions. Some have to do with the fact that some abstractions in the futures ecosystem are leaky today and that makes them less easy to use than they could be (though they won&amp;#x27;t always be leaky[]). But others have to do with understanding the internal implementation of these abstractions - people who feel they must understand how their library works internally before using it.&lt;p&gt;Of course, schedulers are just complicated. Most of the time you don&amp;#x27;t think about how complicated your scheduler is, because its either an OS primitive in the kernel or a language primitive in your language&amp;#x27;s runtime. But since tokio is a library - and modular - it gets criticism for being complex that in my opinion is unfair.&lt;p&gt;[] To be more concrete: a future is essentially a state machine representing the stack state at any yield point; it can&amp;#x27;t (currently) contain lightweight references into itself because they&amp;#x27;d be invalidated when the future is move around. This means using borrowing in futures programs is often infeasible today. Solutions are in the works.</text></comment>