Rendering too slow on website

465 views
Skip to first unread message

Bernd Klein

unread,
May 20, 2021, 4:56:55 AM5/20/21
to MathJax Users
I used
It tells me that the  page
of my website is consuming too much time with mathjax.
Is there any way to speed it up?
The thing is critical, because Google will or has already "punished" my website for this
by reducing the page rank.

Here is the output of "pagespeed/insights":
Reduce JavaScript execution time 2.6 s
Consider reducing the time spent parsing, compiling, and executing JS. You may find delivering smaller JS payloads helps with this. Learn more.
URL
Total CPU Time
Script Evaluation
Script Parse

2,787 ms
2,505 ms
61 ms

Murray

unread,
May 21, 2021, 3:56:36 AM5/21/21
to MathJax Users
Hello Bernd

Ah yes, the hypocrisy of Google insisting you make things fast, while their own bloat (in particular, ads for those sites that can't survive without them) is the thing that most significantly slows down the Web these days.

In your case, your page speed is not bad (better than most pages I analyse). Here are some suggestions to speed things up (at least for initial page load, which is what Pagespeed Insights is mostly concerned with).

(1) Make use of a CDN, so that your pages are served from a server closest to the user. I've been using Cloudflare for a few years now and their free account is more than adequate. I use the "cache everything" setting and once the cache servers have got your content, it speeds things up enormously. As you have hosted MathJax on your server, this will potentially be even faster than using the MathJax CDN, as there is one less server for your page to access.

You should also increase the cache time for most assets - one year is recommended.

(2) The first MathJax math on your page doesn't occur until about 1/2 way down. You could make use of lazy loading so it doesn't start to process your math until just before the user needs it. This would involve:

a) Making use of preload, https://developer.mozilla.org/en-US/docs/Web/HTML/Preloading_content, so the MathJax is loaded when the page loads (but after anything else important for above the fold content is loaded).

b) Making use of an efficient lazy loading script which doesn't use mountains of CPU (and therefore battery and causes lag) as the user begins to scroll down the page. See https://developer.mozilla.org/en-US/docs/Web/API/Document/scroll_event When the user reaches a predefined point (say 500 px above the first bit of MathJax) it would trigger MathJax to process your math.

MathJax v 3 is already quite efficient. It needs time to scan the page, load what fonts it needs and format the math, then paint. I know Davide has put a lot of effort into this aspect for version 3. So there's not much you can do about that. By processing the math after the initial page load, the user's experience isn't held up unnecessarily - only when they actually need the math. 

(3) I looked at several other pages apart from this page and your home page and I found most of them don't used MathJax at all. I suggest you only load the mathjax.js script on pages that actually have math on them - otherwise unnecessary javascript gets loaded and MathJax tries to process math which isn't there (although that's practically instant).

(4) There is actually an error occurring with your startup.js script:

Uncaught TypeError: Cannot set property Package of #<Object> which has only a getter

 I'm not quite sure what your sequence is there but it may also be adding to the processing time.

Also, usually the configuration needs to go before MathJax is loaded, but it seems it comes after on your page, and then startup.js runs. You may wish to revise this flow.

(5) The huge image  fibonacci_score.png is 228 kB on your page is way bigger than the recommended max of 100 kB. use an image optimising service to reduce this and any others on each page.

(6) I came across this page https://www.python-course.eu/fibonacci_to_music_score.php which has LateX but it is not processed because the MathJax script is not loaded on that page.

I hope it helps.

Regards
Murray

Bernd Klein

unread,
May 21, 2021, 5:07:54 AM5/21/21
to MathJax Users
Hello Murray,

Thank you so much. I am so thankful! This is more than I expected. You are right concerning the "hypocrisy of Google".
I will have to go through all your precious hints and I hope that Google will be "satisfied" again in the end.

All the best

Bernd

Murray

unread,
May 22, 2021, 11:24:12 PM5/22/21
to MathJax Users
Bernd

As a challenge, I had a go at your page, implementing much of what I suggested (in case anyone came to here later and wondered what I was talking about).

I simplified your page somewhat to make my life easier, and so that it would work better on a phone (without having to use a PHP-based user agent checker).

I also stripped out 95% of the CSS, which didn't appear to be doing much on this page.  I also moved it inline, to remove a server call.

Here's the result:


For this exercise, the light magenta highlights, and the setting whereby only the math in the middle portion of the page is processed, (and the console log) is so you can see what is going on as you scroll. 

If you add a query string to the URL, you'll see a more realistic version, where it processes down to one whole screen height below the fold, so everything is ready by the time the user scrolls down.


The WebPageTest scores are good (under 0.5 sec for initial page load):


As are PageSpeedTest, with no blocking due to MathJax


It's rough and the short timeouts should no doubt be done in a better way (hopefully Davide will have a suggestion), but it should get you started.

That's the end of the MathJax part. Feel free to reach out privately (murraybourne {{at}} gmail.com) to discuss any of the non-MathJax things that may be affecting your page timings or Google indexing.

Regards
Murray

Davide Cervone

unread,
May 23, 2021, 7:42:59 AM5/23/21
to mathja...@googlegroups.com
Bernd:

Murray has certainly made some good suggestions, and gone above and beyond the call of duty by creating a demonstration page for you.  I was going to give you two possible suggestions myself:  first, either configure mathjax to skip the initial typeset, and then schedule one yourself with a slight delay after the page has loaded (after Google has decided the page is ready, thereby not incurring the MathJax costs in Goggle's computations, or wait to load MathJax entirely until after page load.  Both of these will delay the math's appearance, however.  Second, we are finalizing MathJax 3.2 that we hope to release within a few weeks, and it has a lazy-typesetting extension that does the kind of thing that Murray's code does (and includes some improvements to the CHTML output jax's handling of the CSS to make that more efficient).  At least there are PRs for those features, which haven't yet been merged, but that is the plan.  So my second option would be to wait for v3.2 which should have this built in and use the new extension.

MathJax's lazy typesetting uses an IntersectionObserver rather than scroll events (which can be expensive).  It also makes sure that the previous TeX code is processed so that things like automatic equation numbers and macro definitions are done in the right order.

Davide


-- 
You received this message because you are subscribed to the Google Groups "MathJax Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to mathjax-user...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/mathjax-users/f586613e-f338-4b37-83db-e59fab6001f9n%40googlegroups.com.

Bernd Klein

unread,
May 24, 2021, 12:02:07 PM5/24/21
to MathJax Users
Thank you so much, Davide and Murray! This is so great. Your help goes far beyond of which can be expected and hoped for. It also looks as if it will improve the loading time a lot!
Thank you so much!

Ciarán Kenny

unread,
May 31, 2022, 9:16:32 PM5/31/22
to MathJax Users

Hi,

I believe I’m asking a question that’s already been answered, so my apologies!

I’m using the following to load MathJax on a webpage that’s equation heavy but in which the first equation does not appear until later in the page after some scrolling.

<script>

MathJax = {

  loader: {load: ['ui/lazy']},

  options: {lazyMargin: '500px'}

};

</script>

<script src="https://polyfill.io/v3/polyfill.min.js?features=es6"></script>

<script id="MathJax-script" async src="https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-mml-chtml.js"></script>

Delaying the rendering of my equations has reduced my TBT from about 2 seconds to about 0.7 seconds.

However, the loading of tex-mml-chtml.js itself is what’s taking up about 80% of that remaining 0.7 seconds of TBT.

I believe it’s possible to use IntersectionObserver to delay the loading of the JavaScript file itself until after the page has fully loaded and the user has scrolled, thereby reducing my TBT by that further 80%.

However, I’m a bit lost as to how to implement it. Could someone more knowledgeable give an explanation?

Thanks!

Murray

unread,
Jun 1, 2022, 4:03:22 AM6/1/22
to MathJax Users
Hello Ciarán

You may be interested to see my implementation where I only load MathJax once the user is getting close to any math as they scroll down. It addresses your "I believe it's possible".

See this discussion which has a link to an example page (which scores in the high 90s on Google's Lighthouse):


Regards
Murray

Ciarán Kenny

unread,
Jun 1, 2022, 6:59:05 AM6/1/22
to MathJax Users
Hi Murray,

Thank you for your very quick reply!

That is indeed a lightning fast webpage, but I'm a bit lost as to how you achieved it.

Am I correct in saying that, with my current implementation, MathJax is loaded while the webpage is loaded but the equations are not processed until the user is 500px above the first equation? But, with your implementation, MathJax isn't even loaded until the user is e.g. 500px above the first equation? MathJax will therefore have practically zero impact on page scores with your method, is that right?

What, in addition to the scripts I mentioned, is needed? Was IntersectionObserver used, or something else? And how does one use IntersectionObserver or whatever method was used?

Thanks you again for your time, I really appreciate it! 

Murray

unread,
Jun 3, 2022, 1:35:38 AM6/3/22
to MathJax Users
Hi again  Ciarán

Yes, you are correct. Your current configuration means MathJax is loading when the pages are loading, whether it's needed (yet) or not.

And yes, in my implementation, MathJax is loaded just before it's needed. It isn't even seen by the page testers (and thus your Google score) on load, in cases where there is no math near the top of the page.

Did you manage to have a look at the page source? You can see (in the final javascript on the page) that yes, it uses an intersectionObserver. I found I needed to specify the DOM elements I wanted it to observe on, otherwise it would "double observe" when one element was embedded in another.

Hope you get it working
Regards
Murray

Ciarán Kenny

unread,
Jun 5, 2022, 10:14:04 AM6/5/22
to MathJax Users
Thanks again Murray, I'll have a look at the page console. 

Greatly appreciated!

Reply all
Reply to author
Forward
0 new messages