lol optimizing bluesky feed perf reminds me how misleading so much js framework benchmarking is; all the cost i’m trying to fix now is either about avoiding layout shifts, or about doing stuff as lazily as possible. very little is related to update cost
Comments
riding the NYC subway, apps feel SO much nicer when they’re doing this since data is very on/off.
That's ~15 seconds of CPU from those 2 files on startup. ~1 sec from 391.*.js is bad enough, but ~6s from main.*.js is wild
It sure feels like this is doing too much (right then or in general)
update performance is still important though, b2b style apps suffer heavily from react state management and one of the best things we do is migrating all the state outside of react
how does moving all the logic into the TagMenuInner component help reducing work if TagMenu is rendering it anyways? what exactly is causing it to render on interaction rather than on parent's render
Can someone break this down for me? Really interested how a 20M social media app work!
I visualize it as TagMenuInner not "expanding" until later.
(that said, I'd still 100% split the components as you did)
https://carbon.now.sh/?bg=rgba%28162%2C190%2C211%2C0%29&t=night-owl&wt=none&l=text%2Ftypescript-jsx&width=773&ds=true&dsyoff=20px&dsblur=68px&wc=false&wa=false&pv=31px&ph=32px&ln=false&fl=1&fm=Source+Code+Pro&fs=15px&lh=134%25&si=false&es=4x&wm=false&code=function%2520TagMenu%28%257Bchildren%252C%2520control%257D%29%2520%257B%250A%2520%2520const%2520prefs%2520%253D%2520usePreferencesQuery%28%29%250A%250A%2520%2520%252F%252F%2520lazy%253A%2520these%2520do%2520not%2520run%2520until%2520values%2520are%2520read%2520by%2520renderer%250A%2520%2520const%2520isMuted%2520%253D%2520useComputed%28%28%29%2520%253D%253E%2520Boolean%28%250A%2520%2520%2520%2520%28prefs.value%253F.moderationPrefs.mutedWords%253F.find%28%250A%2520%2520%2520%2520%2520%2520m%2520%253D%253E%2520m.value%2520%253D%253D%253D%2520tag%2520%2526%2526%2520m.targets.includes%28%27tag%27%29%252C%250A%2520%2520%2520%2520%29%2520%253F%253F%250A%2520%2520%2520%2520%2520%2520optimisticUpsert.value%253F.find%28%250A%2520%2520%2520%2520%2520%2520%2520%2520m%2520%253D%253E%2520m.value%2520%253D%253D%253D%2520tag%2520%2526%2526%2520m.targets.includes%28%27tag%27%29%252C%250A%2520%2520%2520%2520%2520%2520%29%29%2520%2526%2526%250A%2520%2520%2520%2520%2520%2520%21optimisticRemove.value%253F.find%28m%2520%253D%253E%2520m%253F.value%2520%253D%253D%253D%2520tag%29%252C%250A%2520%2520%29%29%250A%250A%2520%2520const%2520removeableMuteWords%2520%253D%2520useComputed%28%28%29%2520%253D%253E%2520%257B%250A%2520%2520%2520%2520return%2520%28%250A%2520%2520%2520%2520%2520%2520prefs.value%253F.moderationPrefs.mutedWords%253F.filter%28%250A%2520%2520%2520%2520%2520%2520%2520%2520word%2520%253D%253E%2520word.value%2520%253D%253D%253D%2520tag%250A%2520%2520%2520%2520%2520%2520%29%2520%257C%257C%2520%255B%255D%250A%2520%2520%2520%2520%29%250A%2520%2520%257D%29%250A%250A%2520%2520return%2520%28%250A%2520%2520%2520%2520%253C%253E%250A%2520%2520%2520%2520%2520%2520%257Bchildren%257D%250A%2520%2520%2520%2520%2520%2520%253CDialog.Outer%2520control%253D%257Bcontrol%257D%2520onToggle%253D%257Bv%2520%253D%253E%2520open.value%2520%253D%2520v%257D%253E%250A%2520%2520%2520%2520%2520%2520%2520%2520%253CDialog.Handle%2520%252F%253E%250A%2520%2520%2520%2520%2520%2520%2520%2520%253CShow%2520when%253D%257Bcontrol.isOpen%257D%253E%250A%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%257B%28%29%2520%253D%253E%250A%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%252F%252F%2520lazy%253A%2520only%2520runs%2520when%2520%2560control.isOpen.value%2560%2520is%2520true%250A%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%253CDialog.Inner%2520label%253D%257B_%28msg%2560Tag%2520menu%253A%2520%2524%257BdisplayTag%257D%2560%29%257D%253E%250A%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%257Bprefs.isLoading%2520%253F%2520%28%250A%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%253CView%253E%253CLoader%2520size%253D%2522lg%2522%2520%252F%253E%253C%252FView%253E%250A%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%29%2520%253A%2520%28%250A%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%253CView%253E%250A%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%253CButton%250A%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520label%253D%257B%250A%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%252F%252F%2520isMuted.value%2520only%2520gets%2520calculated%2520here%250A%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520Boolean%28isMuted%29%250A%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%253F%2520_%28msg%2560Unmute%2520all%2520%2524%257BdisplayTag%257D%2520posts%2560%29%250A%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%253A%2520_%28msg%2560Mute%2520all%2520%2524%257BdisplayTag%257D%2520posts%2560%29%250A%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%257D%250A%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520onPress%253D%257B%28%29%2520%253D%253E%2520%257B%250A%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520control.close%28%28%29%2520%253D%253E%2520%257B%250A%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%252F%252F%2520isMuted.value%2520won%27t%2520be%2520recalculated%2520here%250A%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520if%2520%28Boolean%28isMuted%29%29%2520%257B%250A%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520resetUpsert%28%29%250A%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%252F%252F%2520removeMutableWords.value%2520gets%2520calculated%2520here%250A%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520removeMutedWords%28removeableMuteWords.value%29%250A%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%257D%2520else%2520%257B%250A%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520resetRemove%28%29%250A%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520upsertMutedWord%28%255B%250A%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%257B%250A%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520value%253A%2520tag%252C%250A%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520
*useMemo:* compute all values and pass them directly into JSX
*signals/computed:* create boxes that compute their values only when rendered and pass the boxes into JSX
You didn't messed it up in the first place, so that make sense.
1. property updates are stunningly expensive.
2. the renderer isn't the only area where updates could get costly.
3. routing is deceptively expensive.
heavy property updates can bring us down below this target easily, which is a problem for users using mithril to render interactive svgs.
fortunately, in practice, few route templates match, so anything below 0.5ms is a rounding error for almost everyone.