CodeMirror-MathJax icon indicating copy to clipboard operation
CodeMirror-MathJax copied to clipboard

First pass performance

Open cben opened this issue 12 years ago • 6 comments

[migrated from cben/mathdown#19]

The initial render on document load is horribly unacceptably slow (saw 1 minute on a math-heavy page on mathdown.net). The unrendered text does show very fast but it's not very useful since the editor is paralyzed until all math is rendered.


Verified that loading MathJax from the network is not the blocker; it's the rendering itself.


Pasting same text into http://cben.github.io/CodeMirror-MathJax/demo.html typesets much faster (~10s instead of ~60s). Sounds like using CM of fixed size helps a lot. [EDIT: Indeed, switching Mathdown to fixed size helped a lot https://github.com/cben/mathdown/commit/bc6c5c935905cfa012df718666018416a93b9715]


Some rough measurements on a heavy doc:

  • scanning text for the regexp is nearly free (~0.1s)
  • typesetting without markText is not bad - 8s, much of which is due to loading mathjax extensions (=> #21).
    • same with markText without replacedWith! invisible markers are nearly free.
  • everything is at least 2× slower due to logging with an open JS console.
  • full typesetting takes 62s.
    • Chrome profiling suggests a lot of time is spent in visibleLines, (via endOperation←updateDisplay←markText). Indeed text gradually shifts vertically as math is typeset. => Should try keeping view/cursor on top instead of bottom. Naive attempts to wrap with cm.operation don't help because post-Typeset callbacks come one by one.
  • tried an incremental approach => 61s. no loss, no gain. Still makes editor barely responsive. I guess CM's input polling doesn't get much chance to run.

next steps:

  • [x] Queue post-Typeset callbacks and batch via cm.operation.
    • [ ] tune batching vs responsiveness on small edits. Being aware of how many have been queued for mathjax typesetting.
  • [ ] Learn how to run when CM is idle ("update" event?).
  • [ ] On-demand rendering prioritizing math on viewport. (cf. #13)?

P.S. Relevant existing bug:

  • [ ] Don't mess when text shifts around between asking MJ to typeset and callback doing markText(). Hard to trigger now but changes above will make this important.

cben avatar Nov 22 '13 09:11 cben

fb6b5e0fe04a3755a8c90beeba0f55d6ff5dac29 implements queuing and batching post-Typest markText()s into a cm.operation. Keep track of when to flush the queue was easier than I thought - I just MathJax.Hub.Queue() it at the end of the initial pass and of a change event. Effect was surprisingly little — it seems MJ loading and typesetting are the real bottlenecks!

  • Loading locally:
    • Doing all markText() at the end seems to help a bit - from 24–28s to stable 23s.
    • Wrapping them in an operation speeds them from 100ms to 35ms, which is negligible.
  • Loading from GitHub Pages: from 54–59s to 56–58s.

Which begs the question of how fast can MJ typeset all this math at all in a static doc? => 12s locally, 13s with mathjax from github pages. Hmm, something doesn't add up here. Either loading MJ with all extensions takes another half minute or it doesn't?

cben avatar Feb 22 '14 00:02 cben

TODO: try https://github.com/mathjax/MathJax-profiler

cben avatar Jul 16 '14 01:07 cben

  1. It's really important to send many formulas to a single MathJax Typeset() call. I can't find now the detailed post (on mathjax-users?) explaining it, but a major source of MathJax slowness is browser reflows triggered by MathJax measureming sizes, and processing a lot of math in parallel lets MathJax batch many measurements for a single browser reflow.
  2. KaTeX is a newcomer which should make things much faster. It doesn't measure stuff — the API is not even async! Alas, it will take years until it can match MathJax features. Using both with a fallback to MJ is easy and I was about to implement it but procrastinated because I wanted to do (1) first and profile my improvement instead of just doing it blindly. And now we have:
  3. MathJax 2.5 should bring KaTeX-class speed and a release seems around the corner. => At this point I'll just wait for MJ 2.5; doing both KaTeX and MJ 2.5 fallback might not be beneficial, even slower due to double font loading (don't know, need to profile). And there is no point mixing slightly different typesetting styles without clear benefit.

cben avatar Dec 26 '14 13:12 cben

Using MJ 2.5 is blocked on fixing #33. But it didn't really bring "KaTeX-class speed": the CHTML output is fast but not pretty, only usable as preview. A fast preview could still be nice for first-pass performance, but that requires getting separate callbacks from MJ when preview is ready vs final output (which probably involves MJ "signals" but I'm not seeing one for preview). Plus it's tricky to show previews and keep rendering while still chunking preview insertions to reduce reflows.

=> I think KaTeX with MJ fallback (or KaTeX as preview with MJ re-rendering everything?) is the better solution.

cben avatar Jul 14 '15 10:07 cben

Example of viewport-driven typesetting: https://github.com/Dashed/mathjax-lazyload (but it doesn't even attempt off-screen typesetting in the background)

cben avatar Jul 26 '15 08:07 cben

"The upcoming MathJax 2.6 release will bring the CommonHTML output to the quality of the HTML-CSS output."

cben avatar Aug 12 '15 16:08 cben