GNU bug report logs - #78902
31.0.50; [PATCH] Improve performance when computing EWW "readable" page

Previous Next

Package: emacs;

Reported by: Jim Porter <jporterbugs <at> gmail.com>

Date: Thu, 26 Jun 2025 04:58:03 UTC

Severity: normal

Tags: patch

Found in version 31.0.50

To reply to this bug, email your comments to 78902 AT debbugs.gnu.org.

Toggle the display of automated, internal messages from the tracker.

View this report as an mbox folder, status mbox, maintainer mbox


Report forwarded to bug-gnu-emacs <at> gnu.org:
bug#78902; Package emacs. (Thu, 26 Jun 2025 04:58:04 GMT) Full text and rfc822 format available.

Acknowledgement sent to Jim Porter <jporterbugs <at> gmail.com>:
New bug report received and forwarded. Copy sent to bug-gnu-emacs <at> gnu.org. (Thu, 26 Jun 2025 04:58:04 GMT) Full text and rfc822 format available.

Message #5 received at submit <at> debbugs.gnu.org (full text, mbox):

From: Jim Porter <jporterbugs <at> gmail.com>
To: bug-gnu-emacs <at> gnu.org
Subject: 31.0.50; [PATCH] Improve performance when computing EWW "readable"
 page
Date: Wed, 25 Jun 2025 21:56:57 -0700
[Message part 1 (text/plain, inline)]
Currently, when computing the "readable" form of a web page in EWW, we 
make a lot of string copies, which can be slow for large documents. The 
only thing the code is really trying to do is compute the number of 
words in each DOM element, so if we just iterate over the nodes and sum 
up the number of words, it's much faster.

I benchmarked 'eww-readable-dom' with 100 runs on the Wikipedia page for 
"Sun". Here are the results:

  BEFORE: 22.512042s (15.962587s in 269 GCs)
  AFTER:  3.771081s (0.067226s in 1 GCs)

So that's a ~6x improvement in runtime and a ~237x improvement in GC 
time! (And that's in addition to a 4.7x / 5x improvement in runtime / GC 
time from bug#77299, which recently merged.)
[0001-Improve-performance-when-computing-the-readable-form.patch (text/plain, attachment)]

Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#78902; Package emacs. (Thu, 26 Jun 2025 06:35:02 GMT) Full text and rfc822 format available.

Message #8 received at 78902 <at> debbugs.gnu.org (full text, mbox):

From: Eli Zaretskii <eliz <at> gnu.org>
To: Jim Porter <jporterbugs <at> gmail.com>
Cc: 78902 <at> debbugs.gnu.org
Subject: Re: bug#78902: 31.0.50;
 [PATCH] Improve performance when computing EWW "readable" page
Date: Thu, 26 Jun 2025 09:34:18 +0300
> Date: Wed, 25 Jun 2025 21:56:57 -0700
> From: Jim Porter <jporterbugs <at> gmail.com>
> 
> Currently, when computing the "readable" form of a web page in EWW, we 
> make a lot of string copies, which can be slow for large documents. The 
> only thing the code is really trying to do is compute the number of 
> words in each DOM element, so if we just iterate over the nodes and sum 
> up the number of words, it's much faster.
> 
> I benchmarked 'eww-readable-dom' with 100 runs on the Wikipedia page for 
> "Sun". Here are the results:
> 
>    BEFORE: 22.512042s (15.962587s in 269 GCs)
>    AFTER:  3.771081s (0.067226s in 1 GCs)
> 
> So that's a ~6x improvement in runtime and a ~237x improvement in GC 
> time! (And that's in addition to a 4.7x / 5x improvement in runtime / GC 
> time from bug#77299, which recently merged.)

Did you try inserting the text into a temporary buffer and calling
count-words on the buffer?  That sounds like a more natural
implementation to me.  The question is what is its performance?

Thanks.




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#78902; Package emacs. (Thu, 26 Jun 2025 21:28:02 GMT) Full text and rfc822 format available.

Message #11 received at 78902 <at> debbugs.gnu.org (full text, mbox):

From: Jim Porter <jporterbugs <at> gmail.com>
To: Eli Zaretskii <eliz <at> gnu.org>
Cc: 78902 <at> debbugs.gnu.org
Subject: Re: bug#78902: 31.0.50; [PATCH] Improve performance when computing
 EWW "readable" page
Date: Thu, 26 Jun 2025 14:26:58 -0700
[Message part 1 (text/plain, inline)]
On 6/25/2025 11:34 PM, Eli Zaretskii wrote:
> Did you try inserting the text into a temporary buffer and calling
> count-words on the buffer?  That sounds like a more natural
> implementation to me.  The question is what is its performance?

The patch I posted to this bug originally seems to be the fastest by 
far. Using a temp buffer is very close in performance to what we have 
today, which isn't too surprising since eventually we have to allocate 
the same amount of space for either the concatenated string or the temp 
buffer's data.

Here are the benchmarks for 100 runs on the Wikipedia page for "Sun":

  Current master:     50.403511s (34.004043s in 598 GCs)
  Original patch:      3.773581s ( 0.056700s in   1 GCs)
  Temp buffer patch:  49.529317s (33.384452s in 598 GCs)

If you want to try the benchmark out yourself, the form I benchmarked 
was '(eww-readable-dom (plist-get eww-data :dom))'. If you run that 
after loading a page in EWW, it should process the original DOM and 
return a "readable" form of the DOM.

I've attached my temp buffer patch if you want to take a look at it. 
It's possible there's room to improve the performance more, but I doubt 
we could match the perf of the first patch.
[temp-buffer.diff (text/plain, attachment)]

Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#78902; Package emacs. (Fri, 27 Jun 2025 06:27:02 GMT) Full text and rfc822 format available.

Message #14 received at 78902 <at> debbugs.gnu.org (full text, mbox):

From: Eli Zaretskii <eliz <at> gnu.org>
To: Jim Porter <jporterbugs <at> gmail.com>
Cc: 78902 <at> debbugs.gnu.org
Subject: Re: bug#78902: 31.0.50; [PATCH] Improve performance when computing
 EWW "readable" page
Date: Fri, 27 Jun 2025 09:26:07 +0300
> Date: Thu, 26 Jun 2025 14:26:58 -0700
> Cc: 78902 <at> debbugs.gnu.org
> From: Jim Porter <jporterbugs <at> gmail.com>
> 
> On 6/25/2025 11:34 PM, Eli Zaretskii wrote:
> > Did you try inserting the text into a temporary buffer and calling
> > count-words on the buffer?  That sounds like a more natural
> > implementation to me.  The question is what is its performance?
> 
> The patch I posted to this bug originally seems to be the fastest by 
> far. Using a temp buffer is very close in performance to what we have 
> today, which isn't too surprising since eventually we have to allocate 
> the same amount of space for either the concatenated string or the temp 
> buffer's data.

Buffer text allocation is much more efficient, and shouldn't trigger
GC.  So I don't quite understand what you say above, and I understand
even less why we have the exact same number of GC cycles in the
temporary-buffer implementation.  What am I missing?

> Here are the benchmarks for 100 runs on the Wikipedia page for "Sun":
> 
>    Current master:     50.403511s (34.004043s in 598 GCs)
>    Original patch:      3.773581s ( 0.056700s in   1 GCs)
>    Temp buffer patch:  49.529317s (33.384452s in 598 GCs)

OK, thanks.  In that case, I wonder if we should teach count-words
that if the START argument could be a string, in which case it does
what your implementation did.

> If you want to try the benchmark out yourself, the form I benchmarked 
> was '(eww-readable-dom (plist-get eww-data :dom))'. If you run that 
> after loading a page in EWW, it should process the original DOM and 
> return a "readable" form of the DOM.
> 
> I've attached my temp buffer patch if you want to take a look at it. 
> It's possible there's room to improve the performance more, but I doubt 
> we could match the perf of the first patch.

The only way to improve I see is to reuse the same buffer.  But then
again, I don't understand why we had to do so many GCs in this case.




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#78902; Package emacs. (Fri, 27 Jun 2025 07:26:02 GMT) Full text and rfc822 format available.

Message #17 received at 78902 <at> debbugs.gnu.org (full text, mbox):

From: Jim Porter <jporterbugs <at> gmail.com>
To: Eli Zaretskii <eliz <at> gnu.org>
Cc: 78902 <at> debbugs.gnu.org
Subject: Re: bug#78902: 31.0.50; [PATCH] Improve performance when computing
 EWW "readable" page
Date: Fri, 27 Jun 2025 00:25:39 -0700
On 6/26/2025 11:26 PM, Eli Zaretskii wrote:
> Buffer text allocation is much more efficient, and shouldn't trigger
> GC.  So I don't quite understand what you say above, and I understand
> even less why we have the exact same number of GC cycles in the
> temporary-buffer implementation.  What am I missing?

I thought I double-checked all my numbers, but I tried again and now 
have different results; the stats for the current master implementation 
were wrong. Sorry about that. (I guess that explains why the first and 
last numbers were so similar.)

Here are some corrected numbers:

  Current master:     23.626171s (16.733226s in 278 GCs)
  Original patch:      3.742180s ( 0.055775s in 1 GCs)
  Temp buffer patch:  50.049641s (33.544326s in 588 GCs)
  Work buffer patch:  18.712771s ( 8.799703s in 157 GCs)

However, now using a temp buffer is by far the slowest, which I wasn't 
expecting based on your message above. I added a new test though, which 
just replaces 'with-temp-buffer' with 'with-work-buffer'.

So it looks like most of the slowness was buffer creation. With some 
more tests, about half of the time in the "work buffer patch" is in 
'count-words'. Ultimately, my original patch seems to be the fastest, 
and I don't think I'd be able to get a buffer-based version to match the 
performance.




This bug report was last modified today.

Previous Next


GNU bug tracking system
Copyright (C) 1999 Darren O. Benham, 1997,2003 nCipher Corporation Ltd, 1994-97 Ian Jackson.