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

From: Eli Zaretskii <[email-masked]>
Date: Fri, 27 Jun 2014 16:37:50 +0300

> From: Jan Djärv <[email-masked]>
> Date: Fri, 27 Jun 2014 12:44:58 +0200
> Cc: Eli Zaretskii <[email-masked]>,
>  [email-masked]
> 
> 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.

Does it help to set redisplay-dont-pause to nil?

> 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.

We already have the first stage of that in place: that's
redisplay_windows, which is called for each frame that needs to be
redisplayed.  What you are suggesting is to make update_frame, which
currently redraws the frame's windows based on what redisplay_windows
calculated, to instead just mark the areas which need redrawing as
dirty.

That sounds easy enough, but the problem is that we might need more
display updates until the backend decides that it is a good time to
actually redraw.  E.g., the user might type some commands in the
meantime.  AFAIU, what you are saying is let all these changes affect
only the glyph matrices that redisplay_windows calculates, so that
when the backend wants to redraw, the Emacs function that actually
redraws will see the up-to-date glyph matrices and use them.

This could work if the backend can accumulate durty regions
incrementally.  IOW, if it gets 2 requests for areas that partially
overlap, will it mark the union of those areas as dirty?  If not, we
will need serious changes to how redisplay_windows and its subroutines
work, because they currently assume the previous full redisplay cycle
updated everything on the glass, and don't keep record of the glyph
matrices beyond the last redisplay.

Incidentally, I don't think your suggestion will help in the "shake
the divider" scenario: when window dimensions are changed, we toss the
glyph matrices of the affected windows, and then allocate them anew
(and perform a thorough redisplay of those windows).  So this will
anyhow require to redisplay the entire window completely, and the
backend will not be able to save us any redraws.

> 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.

Please show the recipe to reproduce this.  I just tried a naive way of
doing that, and didn't see any mode-line updates even when the mouse
is inside the frame.  So I must be missing something.

> 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.

Isn't this a problem that might make the entire idea unworkable?