GNOME Bugzilla – Bug 775145
View source mode is terribly slow
Last modified: 2017-02-12 01:09:05 UTC
The view source mode I added in bug #738475 is just ludicrously slow. It might not be possible to do JavaScript-based syntax highlighting in the browser at all, or maybe we just need to explore better JS libraries. I think continuing with Prism is not an option, it's just way too slow. I also tried RainbowJS, which was orders of magnitude slower than Prism. I guess I decided that since Prism was such a big performance improvement it was acceptable, but it's really not. If we can't fix this by 3.24 we should go back to using gedit.
The idea of using a JavaScript-based syntax highlighter still sounds reasonable to me. The issue with JavaScript-based syntax highlighters is that is quite difficult to good performance comparisons... So far the only one I have found so far with _actual numbers_ is: http://softwaremaniacs.org/blog/2011/05/22/highlighters-comparison/ Apparently from the three tested (SHJS, SyntaxHighlighter, Prettify, Highligh.hs) the fastest is Highlight.js, but take it with a grain of salt because the post is from 2011... Highlight.js is the one I use on my blog (I have my own static site generator made in JavaScript) and it works well, and one of the things I like about it that the API requires explicitly setting the syntax mode (it does not try to detect from the input) which is a Good Thing™.
Okay, so I went ahead and wrote a quick hack to benchmark the JS syntax highlighters that I could find readily available to be installed with NPM, and ran it over the GNOME web site front page (HTML), the CSS for the Fancybox plugin used in the GNOME web site (CSS), and the main module of the Prism highlighter itself (JavaScript). My conclusions are: * Rainbow is indeed _really_ slow. Avoid. * Prism is not the slowest, but not the fastest either. The difference in speed can be noticeable (e.g. Highlight.js doubles its speed for CSS code. * Highlight.js, which I pointed out in my previous post, is consistently in the top of the results, but... * If we forget about Sublemon (more on it later), the CodeMirror highlighter is the fastest for the slower tests (HTML and JavaScript, likely slower because they are harder to parse), with a solid second position for CSS. I would use this if accurate highlighting is desired. * Sublemon beats them all, in every test. This is because it does not try to parse a particular language, but it has a few generic matching rules that work with most of them to achieve a reasonably pleasant output. This means highlighting may not be 100% accurate, but from what I could see the generated output looks good enough. This can be a reasonable trade-off if we want the absolute fastest JS-based syntax highlighting. The code for the benchmark can be found here: https://github.com/aperezdc/js-highlighters-shootout Full benchmark run output: >>> js highlightJs x 92.47 ops/sec ±3.21% (70 runs sampled) highlights x 58.56 ops/sec ±3.67% (61 runs sampled) illuminate x 71.45 ops/sec ±2.45% (73 runs sampled) codeMirrorHighlight x 108 ops/sec ±4.07% (69 runs sampled) rainbowCode x 5.96 ops/sec ±7.40% (19 runs sampled) sublemon x 134 ops/sec ±2.50% (76 runs sampled) prismJs x 84.06 ops/sec ±3.12% (71 runs sampled) - Fastest: sublemon >>> css highlightJs x 396 ops/sec ±3.19% (83 runs sampled) highlights x 75.43 ops/sec ±3.78% (64 runs sampled) illuminate x 136 ops/sec ±2.93% (77 runs sampled) codeMirrorHighlight x 360 ops/sec ±3.76% (83 runs sampled) rainbowCode x 17.82 ops/sec ±3.06% (38 runs sampled) sublemon x 389 ops/sec ±2.62% (85 runs sampled) prismJs x 222 ops/sec ±2.72% (85 runs sampled) - Fastest: highlightJs >>> html highlightJs x 71.92 ops/sec ±3.81% (64 runs sampled) highlights x 59.05 ops/sec ±3.71% (61 runs sampled) illuminate x 55.30 ops/sec ±2.31% (70 runs sampled) codeMirrorHighlight x 124 ops/sec ±2.72% (76 runs sampled) rainbowCode x 3.24 ops/sec ±7.51% (13 runs sampled) sublemon x 153 ops/sec ±2.42% (77 runs sampled) prismJs x 36.63 ops/sec ±2.62% (63 runs sampled) - Fastest: sublemon
BTW, as you can see from the results, anything that is not Rainbow manages to generate the HTML for the highlighted code dozens of times per second. That should be enough to not end up being “terribly slow”, so I wonder whether the way in which the Prism highlighter is being invoked could be the issue here (and not the highlighter itself). WDYT?
(In reply to Adrian Perez from comment #3) > BTW, as you can see from the results, anything that is not Rainbow manages > to generate the HTML for the highlighted code dozens of times per second. > That > should be enough to not end up being “terribly slow”, so I wonder whether the > way in which the Prism highlighter is being invoked could be the issue here > (and not the highlighter itself). WDYT? Um, that's interesting... maaaybe? It takes 3-4 seconds for Prism to highlight gnome.org in Epiphany here. But the Epiphany-level code is pretty simple....
I took a quick peek at how “ephy-source://” is handled, and it could be that including the “prism.js” script first and then the content, letting the script detect which HTML elements need to be highlighted might have to do with the sluggishness. I would do something like generating the following code: <html> <head> <link rel="stylesheet" type="text/css" href="ephy-resource:///prism.css"> </head> <body> <pre id="highlight" style="display: none">${HTML_SOURCE}</pre> <!-- Do whatever is needed to turn of Prism's auto-detection of code block elements. --> <script type="text/javascript" src="ephy-resource://prism.js"></script> <script type="text/javascript"> let el = document.getElementById('highlight'); el.innerHTML = Prism.highlight(el.textContent, Prism.languages.html); el.style.hidden = ""; // Show the element. </script> </body> </html> Note how the <pre> element is initially hidden, we do the syntax highlighting, update the DOM, and then change the “display” style property *last*. This completely avoids displaying elements while they are getting updated, which saves relayout and redraws. My guess is that relayouts (which are expensive) are the main culprit for highlighting being slow at the moment.
Thanks for investigating, but that doesn't seem to make any difference. :(
The following fix has been pushed: d6dba00 Remove view source handler
Created attachment 345551 [details] [review] Remove view source handler This is still half-baked: it's waaaay too slow. I should never have pushed it.
The following fix has been pushed: 3f322c5 Fully remove view source handler...
Created attachment 345552 [details] [review] Fully remove view source handler... Must have had some mistake with git.