Your strategy essentially trades a one time computation and DOM mutation with a continuous but lighter one with some added overhead. In this case I suspect the total power performance is worse over time; _however_ latency and UX should be _better_, since it removes the relationship between total comments on the page and the time to render avatars, which is currently about 100ms for this page on my machine.
I'm definitely biased towards preferring a one time change and making it as efficient as possible, but when the input has a high enough ceiling I can see how your strategy would make more sense - I'm not quite sure where I stand on HN threads - but thankfully this is just a user script so we can make our own choices :)
This thread is a good perf test, I might give it a quick go.
Also as others mentions the pixelation style thing is now finally fully cross browser supported, which should make it easier to achieve nearest neighbour upscaling for url encoding.
[edit]
I underestimated how involved image format headers are!
Personally I'd leave it created and stop observing the element instead, à la
/* … */ if (entry.isIntersecting) { observer.unobserve(entry.target); /* … */ }
Do you think (or know) that swapping observed node for canvas (potentially producing many canvases) is more expensive than keeping all observers and having smallest possible amount of canvases? (Maybe I'm biased towards saving CPU but saving RAM is better after all?) x.fillStyle = '#' + ((r >> 8) & 0xffffff).toString(16).padStart(0, 6);
to: x.fillStyle = '#' + ((r >> 8) & 0xffffff).toString(16).padStart(6, '0');
as the pad target length is the first parameter of padStart.Not really. You could just create them and not bother removing them. You'd need to check if the user already had an avatar if you did that though, or you'd end up with lots of repeated avatars when you scroll up and down the page.
Could it be faster? Sure, but should it be faster? Not really, IMO, the avatars load very quick, even on a big page.
One suggestion.. rather than creating a canvas for each user using a querySelectorAll and a loop, I'd use an IntersectionObserver and only create the canvases as they scroll into view. That way the user's device won't need to create hundreds of elements when the code runs.