the credit here is due to the 360 people who've contributed to Tokio proper ( https://github.com/tokio-rs/tokio/graphs/contributors), the 236 people who have contributed to Hyper ( https://github.com/hyperium/hyper/graphs/contributors), and so on. <3 https://twitter.com/adamhjk/status/1298343506771992578
as a maintainer, your job is really to set the other 350 or so contributors up for success. when you write code, the target audience is not just your future self or a handful of teammates, but anyone who might ever come along and need to touch it in the future. it's a high bar!
the biggest lesson i've learnt working on tokio — mainly from watching @carllerche — is that in the long run, it really does pay off to slow down enough that you have time to be thoughtful. which runs counter to some of the received wisdom!
this isn't to say that you shouldn't prioritize shipping, but when you cut scope, you take the time to think about *what* scope you're cutting, what you're choosing not to cut, and what the future impacts of this might be.
"can we easily add this later? okay, we'll add it later. are we painting ourselves into a corner if we don't address this now? then we'll address it now. what future designs or implementations would this choice lock us out of?"
the point is not to do all the work up front; if you try to do everything perfect *now*, you'll never have something you can ship. the point is to take enough time to be deliberate about what you're going to do.
getting this right is a pretty delicate dance, but when people are relying on your software in their most important systems, what else can you do?
...which kind of dovetails into another lesson that i think is pretty valuable: we've tried hard to prioritize *predictable* behavior in production, and predictable behavior at scale, over best-case performance or looking good in (ultimately meaningless) microbenchmarks.
(for those of you who were wondering "when is she gonna make this thread be about linked lists, the answer is "now". this is the part where i make this about linked lists.)
predictable behavior in prod is why Tokio's synchronization primitives rely on linked lists to track the tasks that are waiting on them, rather than vector-based queues. a vector can often have much better best-case performance than a linked list...
...but if you grow past the capacity of the vector, you have to reallocate and copy over all the elements. so a normally fast operation is sometimes much, much slower. and, you typically don't shrink the vector over its lifetime, or at least you don't do it very often...
so, if we wrote our asynchronous semaphore using a vector-based queue, we would have memory use that's proportional not to the *current* number of tasks waiting on the semaphore, but to the *maximum* number that have *ever* waited on that semaphore.
if the semaphore is, say, used as a global concurrency limit on incoming HTTP requests, this could be...not great! if you have a bursty workload where you suddenly see way more requests than normal, you have a big spike in resident memory *that might never go back down*.
this is the kind of thing you want to think about when you're working on something that's a fundamental building block of so many people's systems.
You can follow @mycoliza.
Tip: mention @twtextapp on a Twitter thread with the keyword “unroll” to get a link to it.

Latest Threads Unrolled: