💾 Archived View for thelambdalab.xyz › phlog › 2020-06-02-Elpher-rendering-speed.txt captured on 2022-01-08 at 13:43:35.
⬅️ Previous capture (2020-09-24)
-=-=-=-=-=-=-
Elpher rendering speed ---------------------- At the risk of continuing the inanity which has plagued the last few posts, I've just made an update to Elpher that I feel deserves a post on its own. Several people have mentioned (eg [1]) that Elpher can be a bit.. laggy. Some of this no-doubt has to do with its line-by-line approach to inserting text into the buffer when displaying gopher directories and text/gemini documents, which is not easily avoidable. Some of it is also likely to do with performing regexps over the text to identify URLs, which I consider a key feature of Elpher and one which I'm absolutely willing to sacrifice a bit of performance for. Over the past few weeks however I've started to _really_ notice it. This is probably because I've been browsing a bit more gemini, and there tends to be a bit more of a lag there anyway due to the TLS handshake. Again, likely unavoidable, but it managed to bring the situation to my attention again and make me start to wonder what the _real_ problem here was. The situation seemed _particularly_ bad on link-heavy pages, such as [2]. Hrm. So finally I fired up the profiler. Oh yes, did you know - emacs has a built-in profiler for elisp? I mean, of course it does. But still. The profiler reports its results as a hierarchy of function calls with some estimate of the %age of CPU time spent in each. The top level results seemed in line with my intuition. Yes, it's the document rendering function (87%). Yes it's the line rendering function within that (still 87%). Hrm, interesting, it's the button-insertion function within that (STILL 87%). (Emacs calls clickable text in buffers "buttons".) Hold on, what's this though? Within the button-insertion function a function is called to generate the mouseover help-text, and _this_ is using 87% of the CPU time. WTF?? Within that function, it turns out a single library function call to url-encode-url (in order to provide nice normalized URLs in the mouseover text) is using almost all of the CPU time in rendering this particular link-heavy page. How embarrassing!! Of course the first thing I try is just replacing the mousover text with an empty string. My test page loads in a snap - basically an order of magnitude improvement. The profiler wasn't lying! Side note: fixing bugs and squashing performance bottlenecks like this is absolutely the best part of programming! This is _so much fun_! :-) Even though I would have been happy to dispense with mouseover help text entirely for such a performance boost, it turned out I didn't have to. It's a common (and awesome) pattern in the Emacs elisp API for certain variables/properties to accept either a function or a string. The help-echo text property used by buttons has this feature. I'd previously been filling each link button with a pre-generated help text, but what I now do is to just use a reference to a help-text-generating function instead. Thus the help text is generated when it's needed rather than when the page is rendered. (It's currently generated _every_ time it's needed - there's no caching - but this isn't an issue as you don't need to rapidly read mouseover texts over and over again.) SO! As of 2.7.9, rendering speed is _significantly_ improved. The improvement is so major that there don't even have to be _that_ many links on the page to notice it. (For instance, my bookmarks page only contains about 50 links and there used to be a ~0.25s pause every time I visited it. To good approximation this is completely gone.) Yay for profiling! (And boo to url-encode-url! Seriously, wow - so slow!) -- [1]: https://www.emacswiki.org/emacs/CategoryGopher [2]: gopher://cosmic.voyage/1/log