Random list of refactors I rejected as not worthwhile #447
marcustyphoon
started this conversation in
Tech Office
Replies: 1 comment
-
mostly notable for this absolute beauty of a oneliner that I would never actually commit in a non-experimental context: cssCache = Object.fromEntries(await Promise.all(installedScripts.map(async name => [name, await getCss(name).catch(() => null)]))); |
Beta Was this translation helpful? Give feedback.
0 replies
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
-
a.k.a "Marcus' random performance notes, volume 2." I figured someone might find some of these interesting, or they could inspire an idea that turns out to be worthwhile. Collaboration!
exposeTimelines could return all timelines on the page, and callbacks could check if they care about any of the timelines on the page before rendering. multiple lines of code for not much benefit. (also, exposeTimelines gets called multiple times per new posts; see next two bullets)
in theory, onNewPosts could deeply integrate the entire exposeTimelines functionality (
onNewPosts.register(timelineRegex)
; onNewPosts would QSA for timelines, exposeTimelines if necessary, only run callbacks whose timelines exist, filter posts by timeline before handing them to callbacks) - massive amount of code to save like one QSA in a roundbout wayalternately, exposeTimelines could be debounced using queueMicrotask(). this would fulfill the holy trinity of "using all three browser timing functions to debounce things," which while mostly pointless would allow us to save hyrule, and also save maybe 15-30ms.
seen posts only needs to write to localstorage if you actually saw new posts (and you're on the dashboard) instead of on any new posts - saves ~20ms, mostly if you're on a tagged or search page or whatever. see first point, though - kinda odd that it runs at all, really. (this one might be worth doing)
timelineObject injection doesn't really need to run querySelectors for every post; could add a writable object to
window.xkit$whatever
in which injected functions could store data and inject a function on load with a mutationobserver querying for [data-id] that stores a pointer to the relevant dom element (or even the memoized react props) inwindow.xkit$whatever.data.timelineObject[id]
, and then unburyTimelineObject could doconst postElement = window.xkit$whatever.data.timelineObject[id] || document.querySelector(`[tabindex="-1"][data-id="${id}"]`)
- saves about 30-100ms, about 5% of the post load time (imperceptible, and this is the "most impactful" thing on this list)thought about bidirectional messaging with the script body instead of appending script tags in inject() but the saved cpu time is pretty irrelevant, the latency would be worse, and I imagine using eval() would get us kicked out of one of the extension stores (sadly, you can't send functions over a messageChannel). also thought about combining multiple timelineObject injections into one script tag behind the scenes, but again, insignificant speedup.
thought about not serializing inject payloads, but json parse/stringify is really fast so there's no reason to skip it, and it ensures you don't get errors if you accidentally send something disallowed in structured clone, so not worth it (apifetch would need json.parse(json.stringify()), so may as well always do it)
thought about deduplicating the matchingElements filtration step in onBeforeRepaint, since most of the time it's just doing
${postSelector} article
a bunch of times in a row, but this is like one millisecond and I couldn't find a way to organize the extra lines of code that felt worth one millisecond.Beta Was this translation helpful? Give feedback.
All reactions