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