[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: w3m tab line constantly consumes CPU
- From: Michael Heerdegen <michael_heerdegen@xxxxxx>
- Date: Mon, 21 Oct 2013 06:20:37 +0200
- X-ml-name: emacs-w3m
- X-mail-count: 12201
- References: <87k3haj8zk.fsf@xxxxxx> <b4m1u3f8ji4.fsf@xxxxxxx>
Hi,
> In [emacs-w3m : No.12198] Michael Heerdegen wrote:
> > From time to time, I see Emacs constantly consuming CPU, ca. 10%. Emacs
> > doesn't hang, but consumes enough CPU to let my ventilator run all the
> > time.
>
> > It took some time to identify that w3m was the culprit, its tab line,
> > to be more precise. When the tab line is visible, `w3m-tab-line' and
> > `w3m-force-window-update' are constantly run, ca. 10 times per second.
> > Use `trace-function' to verify.
>
> Yes, I knew the tab line eats CPU not a little. I also tried `elp':
>
> M-x elp-instrument-package RET w3m RET
> Run emacs-w3m for a while...
> M-x elp-results RET
> (If necessary, do `M-x elp-reset-all RET' to reset the result.)
>
> According to the result, `w3m-tab-line' and `w3m-force-window-update'
> seem to waste time not so much. So, I was thinking we have nothing
> to have to do if those appetites don't grow anymore.
What you did doesn't necessarily reveal the misery, I think. The loop
causes a _redisplay_ every 0.1 seconds, and this is what eats CPU.
Presumably this isn't shown in your results, because `w3m-tab-line' is
fast, and `w3m-force-window-update' terminates immediately before the
redisplay was performed.
How much CPU it costs depends on the contents of the current w3m window,
and what it displays. A complex page is more critical as "about:".
I checked with profiler.el, M-x profiler-start, etc. When I did nothing
with Emacs, 90% of the CPU time used by Emacs was consumed by the loop.
Absolutely, it makes ca. 5% of CPU usage at my (quite new) laptop.
> > 3. So, after 0.1 seconds, `w3m-force-window-update' is called. This
> > redraws the window's header line, too, so we are back to 1. Ouch!
>
> > I don't want to make a suggestion on how to fix this because I don't
> > know the code well. We have to avoid the loop somehow.
>
> As you might think, another way to update the header line would
> be to make it event-driven. That is, to modify all the functions,
> that change the header line appearance, so as to call `w3m-tab-line'
> if and only if it is necessary.
When I analyze the current code, it makes no sense.
Grep for `w3m-tab-line'. It is only called at one single place in all
w3m files: in the :eval of the header line format of w3m buffers. This
is only called when a redisplay is performed - so why do we need to
trigger another redisplay some time later?
All functions that do stuff making a refresh of the header line
necessary should trigger a redisplay - and that's what they already do,
I think (else, we would never enter any loop).
So, my guess is that removing
(run-at-time 0.1 nil
(lambda (buffer)
(when (buffer-live-p buffer)
(with-current-buffer buffer
(inline (w3m-force-window-update))
(setq w3m-tab-timer nil))))
current)
from `w3m-tab-line' would do nothing harmful but prevent successive
unnecessary redisplays. A short test seems to confirm that.
If we really face a situation where the tab line doesn't get updated, we
will just have to add an explicit redisplay. The current code is only
helpful in a situation where a w3m function does something that changes
the tabs, performs redisplay, and then does another thing changing
the tabs a second time. If there is really such a case, then we should
IMHO handle this case.
Or, do you mean we should even get rid of the :eval in the header-line
format? This would increase performance even more, but this is a
separate issue.
Do you really think that would be hard? I would think that we would
just need to recalculate the header line every time we explicitly
perform redisplay from the code.
Regards,
Michael.