Hi all, I noticed that emacs's performance can depend on the font. For example, Consolas has a much worse performance (scrolling is sluggish) than BitStream Mono. I profiled emacs, and the main difference is "draw_glyphs". When emacs is slow (using consolas), this function takes 50-60% of CPU time (measured by "perf record -g"). When emacs is fast (using BitStream), this function takes only ~2-3%. I played with my font's ascent and descent settings to have more line on the screen (as emacs doesn't support negative line-spacing). Originally, "draw_glyphs" takes 2-3% with my font. But if I decrease the height of the font by modifying ascent/descent, then the same thing happens: draw_glyphs takes 50-60% CPU time. If I set line-spacing to 2, draw_glyphs become normal, 2-3% CPU time. (I'm using a master build from yesterday) Any ideas why this happens? Maybe this happens because lines may overlap and some caching mechanism gets disabled? Thanks, Geza
> From: Herman, Géza <geza.herman@gmail.com>
> Date: Fri, 8 Jan 2021 12:34:53 +0100
>
> I noticed that emacs's performance can depend on the font. For example,
> Consolas has a much worse performance (scrolling is sluggish) than
> BitStream Mono. I profiled emacs, and the main difference is
> "draw_glyphs". When emacs is slow (using consolas), this function takes
> 50-60% of CPU time (measured by "perf record -g"). When emacs is fast
> (using BitStream), this function takes only ~2-3%.
>
> I played with my font's ascent and descent settings to have more line on
> the screen (as emacs doesn't support negative line-spacing). Originally,
> "draw_glyphs" takes 2-3% with my font. But if I decrease the height of
> the font by modifying ascent/descent, then the same thing happens:
> draw_glyphs takes 50-60% CPU time. If I set line-spacing to 2,
> draw_glyphs become normal, 2-3% CPU time.
>
> (I'm using a master build from yesterday)
>
> Any ideas why this happens? Maybe this happens because lines may overlap
> and some caching mechanism gets disabled?
When screen lines can overlap, we have code to handle that, and it
indeed could slow down redisplay. However, you are saying that you
_decrease_ ascent/descent, and I'm not sure I understand how could
that cause overlaps?
In any case, I suggest to profile the code with perf, and see which
parts of the display code (below draw_glyphs) take those cycles with
the problematic font(s). Then we will see which part is the culprit,
and could take it from there.
On 2021-01-08 13:22, Eli Zaretskii wrote: >> From: Herman, Géza <geza.herman@gmail.com> >> Date: Fri, 8 Jan 2021 12:34:53 +0100 >> >> I noticed that emacs's performance can depend on the font. For example, >> Consolas has a much worse performance (scrolling is sluggish) than >> BitStream Mono. I profiled emacs, and the main difference is >> "draw_glyphs". When emacs is slow (using consolas), this function takes >> 50-60% of CPU time (measured by "perf record -g"). When emacs is fast >> (using BitStream), this function takes only ~2-3%. >> >> I played with my font's ascent and descent settings to have more line on >> the screen (as emacs doesn't support negative line-spacing). Originally, >> "draw_glyphs" takes 2-3% with my font. But if I decrease the height of >> the font by modifying ascent/descent, then the same thing happens: >> draw_glyphs takes 50-60% CPU time. If I set line-spacing to 2, >> draw_glyphs become normal, 2-3% CPU time. >> >> > When screen lines can overlap, we have code to handle that, and it > indeed could slow down redisplay. However, you are saying that you > _decrease_ ascent/descent, and I'm not sure I understand how could > that cause overlaps? In fontforge, I made these values smaller. So, this causes that emacs will display the font as if line-spacing were negative. So, lines start to overlap, because the actual height of the glyph doesn't change, but the vertical spacing between them is smaller. > In any case, I suggest to profile the code with perf, and see which > parts of the display code (below draw_glyphs) take those cycles with > the problematic font(s). Then we will see which part is the culprit, > and could take it from there. I did a perf record with emacs -Q, the results are better than my full configuration, but the difference is still there (now I see that there is a function which has a telling name about overlap: gui_fix_overlapping_area): - 27.75% draw_glyphs - 18.80% gui_fix_overlapping_area - 18.63% update_window update_window_tree update_frame - redisplay_internal - 10.33% read_char read_key_sequence - 8.09% read_key_sequence command_loop_1 + 0.17% draw_phys_cursor_glyph - 8.86% gui_write_glyphs - 7.93% update_window_line update_window update_window_tree update_frame - redisplay_internal + 4.51% read_char + 3.33% read_key_sequence + 0.93% update_window With larger line-spacing, this function takes 0.86%: 0.86% - 0.76% gui_write_glyphs update_window_line update_window update_window_tree update_frame - redisplay_internal - 0.63% read_char read_key_sequence 0.10% draw_phys_cursor_glyph But the overall effect is that with the overlapping setting, scrolling is sluggish. If there's no overlap, scrolling is smooth, so I think that actually there's a larger difference than the additional 25% CPU usage. It's not a big deal of course (otherwise emacs works OK, it's just the scrolling which is not smooth).
> Cc: emacs-devel@gnu.org
> From: "Herman, Geza" <geza.herman@gmail.com>
> Date: Fri, 8 Jan 2021 14:46:10 +0100
>
> - 27.75% draw_glyphs
> - 18.80% gui_fix_overlapping_area
> - 18.63% update_window
> update_window_tree
> update_frame
> - redisplay_internal
> - 10.33% read_char
> read_key_sequence
> - 8.09% read_key_sequence
> command_loop_1
> + 0.17% draw_phys_cursor_glyph
> - 8.86% gui_write_glyphs
> - 7.93% update_window_line
> update_window
> update_window_tree
> update_frame
> - redisplay_internal
> + 4.51% read_char
> + 3.33% read_key_sequence
> + 0.93% update_window
>
>
> With larger line-spacing, this function takes 0.86%:
>
> 0.86%
> - 0.76% gui_write_glyphs
> update_window_line
> update_window
> update_window_tree
> update_frame
> - redisplay_internal
> - 0.63% read_char
> read_key_sequence
> 0.10% draw_phys_cursor_glyph
>
> But the overall effect is that with the overlapping setting, scrolling
> is sluggish. If there's no overlap, scrolling is smooth, so I think that
> actually there's a larger difference than the additional 25% CPU usage.
If screen lines overlap with the offending font, then the difference
could be justified, because redrawing one screen line would require
redrawing the two adjacent screen lines. I'm a bit surprised by the
large performance hit, though, so maybe it's worth looking at the code
which gets run in the slow case, to see maybe some unnecessary work we
are doing in that case.
Do you have very wide windows, per chance? Does the problem becomes
smaller if you make your frames and windows narrower?
On 2021-01-08 15:35, Eli Zaretskii wrote:
> If screen lines overlap with the offending font, then the difference
> could be justified, because redrawing one screen line would require
> redrawing the two adjacent screen lines. I'm a bit surprised by the
> large performance hit, though, so maybe it's worth looking at the code
> which gets run in the slow case, to see maybe some unnecessary work we
> are doing in that case.
>
> Do you have very wide windows, per chance? Does the problem becomes
> smaller if you make your frames and windows narrower?
Yes, my full screen emacs has a width of ~270. Sometimes I use this as a
full screen window, sometimes I split it into two with
split-window-horizontally.
And yes, the problem becomes smaller if I make the window narrower, or
if the screen contains less characters. This problem is most visible at
a particular part of my code which contains a larger table, with long
lines (~160).
I disabled redrawing caused by overlapping by commenting out the line
which sets the "row->overlapping_p" flag (xdisp.c:21752), and the
problem is gone away. But my fonts are clipped (not a surprise). But, it
fixed the consolas case as well, and I don't see any clipping with this
font. Maybe overlapping detection is too strict (I mean, emacs considers
cases overlapping which are close to overlapping, but they aren't)? Or
maybe I just don't notice the clipping.
> Cc: emacs-devel@gnu.org
> From: "Herman, Geza" <geza.herman@gmail.com>
> Date: Fri, 8 Jan 2021 16:38:10 +0100
>
> I disabled redrawing caused by overlapping by commenting out the line
> which sets the "row->overlapping_p" flag (xdisp.c:21752), and the
> problem is gone away. But my fonts are clipped (not a surprise). But, it
> fixed the consolas case as well, and I don't see any clipping with this
> font. Maybe overlapping detection is too strict (I mean, emacs considers
> cases overlapping which are close to overlapping, but they aren't)? Or
> maybe I just don't notice the clipping.
It could be that in the case of Consolas the overlapping doesn't
actually happen, but some metrics we get from the font tell us they
are. Or maybe they do happen, but only when very few characters from
the font are used. Or maybe this also depends on the font backend,
like whether you build with or without Cairo.
This calls for some font expert(s) to study the Consolas case and see
why the problem happens there. Perhaps we could speed up at least
that case, I don't know.
On 2021-01-08 16:46, Eli Zaretskii wrote:
>> Cc: emacs-devel@gnu.org
>> From: "Herman, Geza" <geza.herman@gmail.com>
>> Date: Fri, 8 Jan 2021 16:38:10 +0100
>>
>> I disabled redrawing caused by overlapping by commenting out the line
>> which sets the "row->overlapping_p" flag (xdisp.c:21752), and the
>> problem is gone away. But my fonts are clipped (not a surprise). But, it
>> fixed the consolas case as well, and I don't see any clipping with this
>> font. Maybe overlapping detection is too strict (I mean, emacs considers
>> cases overlapping which are close to overlapping, but they aren't)? Or
>> maybe I just don't notice the clipping.
> It could be that in the case of Consolas the overlapping doesn't
> actually happen, but some metrics we get from the font tell us they
> are. Or maybe they do happen, but only when very few characters from
> the font are used. Or maybe this also depends on the font backend,
> like whether you build with or without Cairo.
>
> This calls for some font expert(s) to study the Consolas case and see
> why the problem happens there. Perhaps we could speed up at least
> that case, I don't know.
Okay, thanks for the help! I adjusted my font's ascent/descent, and now
I don't see any clipping with this font either (for the record, I'm
using Cairo).
If I have the time, I may have a look at this part of emacs's code and
try to understand what's going on exactly.