🌠 It's so easy to get sucked into performance micro-optimization territory.
Someone will say that Method X is slow, and inevitably somebody else will point out that it doesn't really matter outside of contrived, unrealistic benchmarks.
🧵 I wanna dig into that a bit…
Here's an example. We have a list of users, and we wanna filter so that we only show the people who are online.
We can do that with a "filter", or with a "reduce", or with a "forEach". Which is faster? Does it matter? Why or why not?
Browsers come with a "Performance" API that lets us take high-res snapshots, offering sub-millisecond precision, so we can measure small gaps.
Here's what that code looks like:
(Quick caveat: In an effort to reduce fingerprinting, some browsers will limit the precision of this DOM API. In Firefox, you can temporarily loosen this restriction by setting the "reduceTimerPrecision.microseconds" setting to 1)
In the current setup, with 250 items in the array, here's how long various methods take:
(Approximate numbers, running each one 10 times and taking a rough average)
The slowest of these is incredibly quick. In the span of a human blink, the `reduce` solution can run over 1000 times.
But that's with 250 items. What if the # of items was much, much bigger? The reduce solution is 2x slower, won't that matter when we have millions of items?
We don't need to worry about that on the front-end, because we won't ever have millions of items. If we did, we'd have *way bigger* problems than the JS iteration speed.
The reason we iterate through data is because we want to render something, and rendering is *expensive*.
Google recommends that our page shouldn't have more than 1500 DOM nodes, total. DOM nodes consume a lot of memory, and the browser will explode if we try rendering millions of them. We should paginate our data, so that we're only dealing with small amounts at a time.
Our code example filters for users that are online, which happens to be about 50% of them. If I increase that number to 2500, we get awfully close to that DOM node limit.
The slowest method still only takes ~175μs (0.175ms). The performance doesn't scale linearly.
Now, there is a clever technique called virtualization that can help us here.
The idea with virtualization is that we only render what's in the viewport (along with a bit of a "buffer"). In theory, we only have to pay for the elements we can see at one time.
Virtualization is a fantastic technique and should absolutely be used when dealing with large data, but it doesn't give us carte blanche to have infinitely large data sets!
All of that data still needs to come over the wire, and make it to the user. If we try to send 100,000 objects, that payload will be big and slow, and it'll take a while for the browser to download and parse it, even before getting to any iteration.
There are also memory concerns; once we receive this data, we have to hold it in RAM. Modern devices have a lot of it, but they also have a lot of Chrome tabs to manage.
It's just never a good idea to be dealing with millions of items in JS. Not on the front-end. And not really on the back-end either. Databases are good at doing this stuff. We should be doing it at the database layer.
If we use virtualization, we *might* be able to get away with 10k items. Maybe.
With 10k items, the slowest "reduce" method still takes less than 1ms (~400μs).
I can guarantee that many other steps in the render process will be orders of magnitude slower than this.
Some context around human time perception: if something happens within 100ms or less, it'll feel instant for us. If I click a button and the screen has repainted in <100ms, it feels snappy AF.
(the exception is animation: if something is moving across the screen, we need to repaint it 60 times a second for it to feel fluid, which works out to 16.6ms per frame.)
(Either way, though. JS iteration time is a drop in the bucket.)
I think we often lose the forest for the trees when we talk about performance. We get caught up in the metrics. Really, the only thing that matters is if the user gets bored waiting for our page to load/react.
A rant for another day: _perceived_ performance matters way more than raw transfer/load speeds, but it's harder to measure / fit into a KPI.
UX optimizations, not JS optimizations, are often the lowest-hanging fruit.
When iterating in JS, it's way more important to focus on readability. Choose the method that is easiest to understand, not the one which is fastest. Especially on the front-end, there are bigger fish to worry about when it comes to performance.
If you still find yourself worrying that a particular method may be slow, you can always measure it! In fact, this is a good habit to get into, as it helps build your intuition for what's quick & what's slow.
Combine this with profiling layout/paint times for a sense of scale 😄
Thanks for reading all the way through; this thread got longer than I expected 😅
If you'd like to learn more about performance optimizations on the front-end, I go way deeper in my 2019 React Rally talk:
• • •
Missing some Tweet in this thread? You can try to
force a refresh
Are you interested in teaching stuff to developers? Maybe through a blog, or a workshop, or an online course?
🧵 This thread is a quick summary of some of the most-critical stuff I've learned, over years of blogging, teaching at a bootcamp, and working in edtech at Khan Academy.
I believe that there are two categories of learning: active and passive.
Active learning means that the learner is doing something. They're solving a problem, writing some code, playing with an example. Passive learning is watching a video, listening to a lecturer.
Which one is better? Well, I think active learning is probably more effective, but it's also more draining. Nonstop active learning is *exhausting*.
I like to treat it like interval training: I intersperse both types, so that we're constantly hopping between them.
From March 2020 to ~October 2020, I wasn't really able to use a keyboard/mouse.
I've been pretty public about how I worked around it (joshwcomeau.com/blog/hands-fre…), but I haven't been as public about how I overcame it.
🧵 This thread is about my personal experience with RSI.
This is a story about my own experience, not a tutorial for how to solve RSI. Everyone's different, and just because something worked for me doesn't mean it'll work for you.
Please read all the way through before trying anything.
[cw medical stuff / surgery discussion]
In March 2020, I injured my left arm. Certain activities, like typing, would cause a burning pain in the elbow, and occasionally the wrist or fingers.
In May 2020, the same thing started happening in my right arm.
Around this time tomorrow (10AM EST), I'll be launching my first product as an indie hacker, CSS for JavaScript Devs (css-for-js.dev).
It has been one heck of a ride 😅. In this thread, I wanna share what the journey's been like ✨
In early 2020, I developed an RSI that made it impossible to use a keyboard/mouse. I spent months not using a computer at all, and then months training myself to code with dictation and an eye-tracker.
It's mostly better now, but this was a catalyst for my abrupt career change.
I mention this because I think it's important framing: I'm not the type of person that would typically quit their secure, very-well-paid job as a staff engineer *during a pandemic* to pursue an unproven venture. But it felt urgent to me that I do this right now.
One of these numbers-in-circles is correctly centered. The other one *looks* correctly centered. 😅
Can you tell which is which?
Explanation in-thread 👇
With “true” mathematical centering, you get the result on the left. This is what happens by default in HTML/CSS. It centers the number according to an invisible box.
If we shift it a few pixels to the right, its stem aligns with the Y axis, and it looks ever-so-slightly nicer 💖
I wrote a blog post all about these sorts of small tweaks, “Chasing the Pixel-Perfect Dream“: joshwcomeau.com/css/pixel-perf…
It reminds me of a well-tended garden. Each plant that you prune has a negligible impact, but in aggregate, it makes a huge difference.
In Summer 2020, I was trying to figure out what I wanted to teach. Maybe Gatsby, since I worked for the org? Maybe React, since I had been using AND teaching it for years? Maybe whimsical animations, since that's my whole jam?
I picked… CSS.
Explanation in-thread 👇🏻
First, some brief context: In 2020, I developed an RSI that left me unable to type or use a mouse. It's mostly better now, but it was an eye-opening experience, and one that convinced me that it was time to do something I had wanted to do for years: focus exclusively on teaching.
For a few years I've been teaching part-time at a local coding bootcamp. It's super fulfilling work, because I can see the impact I have on students looking to start a new career.
Impact is important to me. I wanted to teach something that would meaningfully affect people!