I mist write about cliche, racism, bias and the Hyper-Message
Out of stress, I was playing with the background patterns of my Macintosh System 6, and then I wanted to see how can I create a magenta with the colors there. Given the resolution of emulation, you have a pattern that is absolutely impossible to read. And so, I used pink, red, dark blue, green, and a bit of gray to achieve this magenta like color with the ways pixels are usually put on displays and engines like Skia optimize for them…
The computer really is a folk instrument. Electronic music is like folk music.
I mean, people pass around sound samples, and do remixes, and the same way that folk music is passed around; in people with different lyrics, different orchestrations, different improvisations, you know… it’s the computer; and electronic music in general are folk media.
Yielding with setTimeout involves a minimum delay3, so each piece can end up waiting a few milliseconds for nothing. Usually this doesn’t matter, but in situations that demand a very high level of responsiveness, the delay can become a problem.
That’s why some code schedules the next task by posting a message through a MessageChannel instead. React’s scheduler uses this method. More recently, a standard API called scheduler.yield() has also appeared to address this problem. Its advantage is that after yielding, the original work resumes ahead of other queued tasks instead of being pushed to the back. Browser support is still uneven, though.
To the user’s eye, the element glides from its old spot to its new one, but in reality the element has already arrived at its new spot, and the transform briefly drags it back before releasing it into place. While the animation plays, the only per-frame work is the compositor interpolating a transform. Most list-reordering animations are built this way, and Vue’s TransitionGroup and Framer Motion’s layout animations are FLIP under the hood.
The fix [
Two things worth knowing before handing work to the compositor. One is will-change: transform. It gives the browser a hint that “this element is about to change, so prepare it as its own layer in advance,” which can smooth out the start of an animation. Overuse it, though, and the number of layers balloons and memory gets wasted instead.
The other is reading layout values, which you just saw in the FLIP code. If you get the ordering wrong between code that reads layout values (getBoundingClientRect, offsetWidth) and code that writes styles, you run into a problem called layout thrashing.
What happens if chat pours in faster than the throughput? Arrivals outpace processing, the backlog keeps growing, and the messages reaching the screen get older and older. This situation is called backpressure.
The compositor thread is the reason the CSS animation didn’t stop. Transform and opacity don’t change an element’s position, size, or color in the document. They move an already-painted layer or adjust its transparency, so there’s no need to redo layout or paint. That lets the browser handle them directly on the compositor thread without going through the main thread at all. Even when the main thread is busy, the compositor runs separately, so the animation stays smooth.
The main thread can do nothing while a task is running. The rendering pipeline that produces frames can’t cut into the middle of a task either. It can only run between tasks. Yielding is the act of creating those gaps. The backlogged input and frame production get their turn in the gaps, and to the user it feels as though performance improved.
But what about animations where the layout genuinely has to change? Picture a list where deleting an item makes the items below it slide smoothly up into place. This isn’t decorative motion. The positions really do change. Yet animating top means layout on every frame. The technique that resolves this dilemma is FLIP (First, Last, Invert, Play)6. In short, you cause exactly one layout change and leave the entire movement to transform. It goes in this order.
First: measure the position before the move
Last: actually change the layout and measure the new position. Layout happens exactly once, here
Invert: apply a transform to the element in its new position so it appears to still be in the old one
Play: animate that transform away. This part belongs to the compositor
Teve Ross was a legend. Starting with nothing but a job at his father-in-law’s funeral parlor, he built Time Warner into one of the world’s largest companies, making a mark on every part of the media landscape. MTV and Nickelodeon were born under his roof. He bought and ran Atari. He helped found the New York Cosmos and, with it, professional soccer in America. When Ross died in 1992, Clint Eastwood dedicated his Best Picture Oscar for Unforgiven to him; two years later, Steven Spielberg did the same with Schindler’s List.
Everyone glosses over the boring part. To build the stake he needed to get into the media business, Ross bought and built a string of strikingly mundane companies in the 1950s and ’60s. He started by convincing his father-in-law to let him rent his funeral parlor’s limousines out at night, when they weren’t being used. Then he founded a rental car company, merged it with a parking lot business, bought a cleaning business, and took the whole thing—including the funeral parlor—public as Kinney Services. Ross used Kinney to buy a flooring company, a painting company, a carpentry company, and a plumbing company. He then parlayed this hodgepodge of everyday businesses into acquiring the legendary Warner Bros. Movie studio.
Raising throughput takes a different tool than splitting. For example, instead of drawing messages one by one, you can draw the accumulated batch in one go. The fixed per-message cost folds together, and the same amount of time renders more chat. Being told to split and then told to batch may sound like a contradiction, but the point of both is to trim tasks to an appropriate size. Splitting deals with tasks so long that rendering can’t squeeze in, and batching deals with tasks so frequent that the pipeline’s fixed cost is paid over and over.