Skip to content

WIP: faster markdown#28992

Closed
chrisnojima wants to merge 7 commits intonojima/HOTPOT-next-670-cleanfrom
nojima/HOTPOT-faster-markdown
Closed

WIP: faster markdown#28992
chrisnojima wants to merge 7 commits intonojima/HOTPOT-next-670-cleanfrom
nojima/HOTPOT-faster-markdown

Conversation

@chrisnojima
Copy link
Contributor

@chrisnojima chrisnojima commented Mar 6, 2026

Faster markdown parsing

Changes:

  1. Fast-path for plain text — 3 tiers: none/serviceOnly/full parse level. Plain text messages skip parsing entirely.
  2. Plain text fast path for all modes — preview, serviceOnly, serviceOnlyNoWrap, regular rendering.
  3. Lightweight service-only parser — 6 rules instead of 15 for messages with only $>kb$ decorations.
  4. AST parse cache — LRU (200 entries) avoids re-parsing same text on re-render.
  5. ServiceDecoration JSON cache — LRU (500 entries) for base64+JSON decode.
  6. Hoisted default styleOverride — prevents new {} on every render.
  7. Removed ErrorBoundary on mobile and fast paths.
  8. Hoisted blockQuote regexes — moved from function body to closure.
  9. Simplified serviceDecoration matcher — removed wrapper function.
  10. Fast-path text regex — skip TLD matching when no .@: in source.
  11. Removed lodash isArray — use native Array.isArray.
  12. Removed dead noMarkdownParser code.

Results (inbox scroll, 300 small rows):

Metric Baseline After Change
React total 6252ms ~5600ms ~-10%
InboxRow-small 2481ms ~2230ms ~-10%
FPS avg 52.9 ~54 ~+2%
FPS min 16 43+ better
FPS p5 32 46 +44%
  • test thread
  • i see non parsed service decorations

chrisnojima and others added 7 commits March 5, 2026 23:26
- Add fast-path for plain text: skip parser entirely when no markdown
  chars or service decorations are present. Handles preview, serviceOnly,
  serviceOnlyNoWrap, and regular rendering modes.
- Add lightweight service-only parser: for messages with service
  decorations but no markdown formatting, use a parser with only 6
  rules instead of 15.
- Cache parsed ASTs: LRU cache (200 entries) keyed on input text +
  parse level avoids re-parsing the same message on re-render.
- Cache service decoration JSON: LRU cache (500 entries) for the
  base64 decode + JSON.parse in ServiceDecoration.
- Hoist default styleOverride to avoid new object on every render.
- Skip ErrorBoundary on mobile (unnecessary wrapper).
- Remove dead noMarkdownParser code.
…jis to full parser

- Restore serviceOnlyTextRegex that stops before $>kb$ tags, unicode
  chars, colons (emoji shortcodes), and newlines. The greedy [source]
  text rule was consuming service decoration tags.
- Add emojiQuickCheck to getParseLevel so text containing emoji
  shortcodes or unicode emojis routes to 'full' instead of 'none',
  which skipped emoji rendering entirely.
…est, fix lint

- Add PerfProfiler wrappers to markdown output components (MD-total,
  MD-paragraph, MD-serviceDecoration, MD-emoji) for fine-grained
  render timing via React Profiler
- Add thread scroll Maestro perf test (perf-thread-scroll.yaml)
- Speed up inbox/teams scroll Maestro tests (duration 150→10ms,
  waitToSettleTimeoutMs 10)
- Fix serviceOnlyTextRegex to stop before colons (emoji shortcodes)
- Fix emojiQuickCheck: split into cheap nonAsciiCheck + expensive
  unicodeEmojiCheck to avoid 14K regex on every message
- Fix no-control-regex lint warning on nonAsciiCheck

Co-Authored-By: Claude Opus 4.6 <[email protected]>
@chrisnojima chrisnojima closed this Mar 6, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant