Subject: Re: bug#17124: 24.3.50; Occasional Extremely Slow Redraws in OSX Emacs

From: Jan Djärv <[email-masked]>
Date: Fri, 27 Jun 2014 12:44:58 +0200

Hello.

1 apr 2014 kl. 18:57 skrev Eric Froemling <[email-masked]>:

> 
> On Apr 1, 2014, at 8:03 AM, Eli Zaretskii <[email-masked]> wrote:
> 
>>> From: Eric Froemling <[email-masked]>
>>> Date: Mon, 31 Mar 2014 22:23:33 -0700
>>> Cc: [email-masked]
>>> 
>>> Ok here’s some further info/possible repro case if it is of use:
>>> I built my own emacs by doing a bzr branch bzr://bzr.sv.gnu.org/emacs/trunk,
>>> then autogen.sh and ./configure —with-ns
>>> I removed my .emacs file so as to get default settings, then launched emacs,
>>> opened a large text file, and subdivided the frame into several windows.
>>> With this setup it is quite easy for me to get the slowdown to happen by just
>>> dragging a divider around for a bit.
>>> Here’s a clip of a slowdown with the activity monitor visible:
>>> https://www.youtube.com/watch?v=olkyqVOWSLs
>>> You can see that emacs is only using a few percent cpu throughout the slow redraw,
>>> whatever that may imply.
>> 
>> If Emacs does not use too much CPU cycles, it's probably not an Emacs
>> problem.
> 

It actually is.  Emacs draws too much, and the backing store gets swamped with requests.
See https://developer.apple.com/library/mac/documentation/Performance/Conceptual/Drawing/Articles/FlushingContent.html
and
https://developer.apple.com/library/mac/technotes/tn2133/_index.html

With the "shake the divider" recepie (see below), redisplay_internal is called more than 30 times per second.  On an old computer (end of 2008) I get about 37 times per second.
But each redisplay results in multiple draw_begin/end, so for drawing, it is more than 37 times per second.

What we would need is for redisplay to be more in line with what toolkits does w.r.t. drawing.
First calculate all glyphs, but don't do any drawing.
Then invalidate those regions that needs redraw (a new RIF function), and let the backends deside when it is appropriate to draw by calling a redisplay function that does the actual drawing, based on the latest glyphs.  This was suggested here:

http://lists.gnu.org/archive/html/emacs-devel/2010-07/msg00821.html

with some further discussion about here:

http://lists.gnu.org/archive/html/emacs-devel/2013-04/msg00433.html

I think there is room for optimizations in the generic display also, for example moving the mouse redraws the entire mode line, even if the mouse pointer is outside the frame.

>> 
>>> I’ve also attached a sample I took of emacs during such a slowdown.
>>> It looks like a lot of calls are blocking in _CGSSynchronizeWindowBackingStore
>>> under the hood.
>> 
>> I don't know how to read that.  Are the numbers there CPU times, or
>> are they numbers of calls to each function?  If the latter, then they
>> are not very useful in this case.
> 
> You can see the total samples per thread broken up down into the call chain.
> ..so in the main thread the time seems to be somewhat evenly divided between
> draw_glyphs, draw_window_fringes, etc, all of which seem to be blocking
> in _CGSSynchronizeWindowBackingStore.
> 
> Can anyone try to repro this?  (basically open a large buffer, subdivide a
> frame into quite a few windows, and then vigorously shake a horizontal
> divider for a bit.  In my case I usually get a slow refresh after 5-15 seconds).
> It can happen in other cases too such as window resizes but this seems
> to be the easiest way to trigger it.
> I’m using a pretty vanilla OSX Mavericks install on a retina MBP; curious
> if others are seeing this..
> 

It is easy to trigger by shaking the divider.
I can sort of fix this by replacing some flushWindow with setNeedsDisplay:YES.
This has the drawback that updating the frame while shaking the divider becomes slower, and sometimes stops updating the frame at all until I stop moving the mouse.

	Jan D.