emacs-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Scrolling commands and skipping redisplay, was: Re: emacs rendering


From: Eli Zaretskii
Subject: Re: Scrolling commands and skipping redisplay, was: Re: emacs rendering comparisson between emacs23 and emacs26.3
Date: Fri, 24 Apr 2020 12:51:21 +0300

> Cc: address@hidden, address@hidden, address@hidden, address@hidden,
>  address@hidden
> From: Dmitry Gutov <address@hidden>
> Date: Fri, 24 Apr 2020 04:23:57 +0300
> 
> > I suggest to use a common terminology, otherwise we will just confuse
> > each other.  Let's agree to call "redisplay" only what happens when
> > Emacs calls one of the two functions: redisplay_internal and
> > echo_area_display.  OK?  Redisplay calls many functions, including
> > fontification-functions, but those functions themselves are not to be
> > called "redisplay", because they don't display anything.
> 
> Do scrolling commands and/or code that calls posn-at-point do anything 
> else common with redisplay other than fontification functions?

"Common" is too general a word to give an intelligent and helpful
answer to your question.  I have no other way except explaining a lot
of how relevant parts of the display engine work (below), or else we
will be forever trapped in misunderstandings.  (I do suggest to read
the commentary and the code in xdisp.c, to facilitate better
communications.  It takes time and non-trivial effort to write these
descriptions.)

> For instance, converting the buffer text into some other structure that 
> rendering the window will be based on. I think you called it a "glyphs 
> table" or something like that.

You mean the glyph matrices.  There are two matrices for each window
on display: the "current" matrix and the "desired" matrix.  The
current matrix describes what's currently on the glass.  The desired
matrix is created during each redisplay cycle and describes what
_should_ be on the glass; it is generally sparse, i.e. holds only
parts of the window's screen lines, because the display engine decided
only those parts need to be updated for this cycle.  The desired
matrix is used to update what's on the glass, and then its "glyph
rows" (each row corresponds to a screen line) are copied into the
current matrix (thus making the current matrix up-to-date), and then
the desired matrix is discarded.

Glyph rows in the desired matrix are produced by the functions
display_line (which handles buffer text and any display/overlay
strings put on buffer text via text properties and overlays), and
display_string (which handles Lisp or C strings unrelated to any
buffer, like what we do with mode/header/tab-line, menu-bar on TTY and
non-toolkit GUI frames, etc.)  These two functions use the "iterator"
object ('struct it', see dispextern.h) to iterate the object, whether
a buffer or a string, one character position at a time, and produce
the glyph structures which are elements of glyph rows.  The iteration
includes a lot of logic, but basically is built on 3 low-level
subroutines: set_iterator_to_next (which moves the iterator to the
next "display element"), get_next_display_element (which figures out
what kind of display element -- a character, a character composition,
an image, a stretch of white space, an xwidget -- is that element, and
fills the relevant fields of the iterator object with the data for
that element), and PRODUCE_GLYPHS, which is a macro that invokes a
produce_glyphs method of the window's frame, and fills up the glyph
structure of the next element of the glyph row.  The produce_glyphs
method also updates the running row metrics fields within the iterator
object, ones that keep track of the current pixel position, the
height, ascent, and descent of the row, etc.  JIT fontification
happens inside get_next_display_element, when it detects that it came
upon buffer text that doesn't have a non-nil 'fontified' property.

Scrolling commands, posn-at-point, and others that need layout
information of any kind, use the functions that simulate the display.
Those functions do NOT produce any glyph rows.  They use the
move_it_in_display_line function, which invokes the same 3 subroutines
as display_line and display_string, and with a similar surrounding
logic, but their only purpose is to move the iterator object in the
same way as redisplay would, keeping the metrics, but without producing
any glyphs.

I hope you can now figure out the answer to your question about the
"common" parts.

> If *that* work (together with fontification) is usually what takes the 
> most time during redisplay

This remains to be shown.  Someoneā„¢ should profile redisplay in
relevant use cases and present the profiles, then we could decide
whether this is or isn't the case.  Personally, I think it's roughly
40%-60% or 30%-70%, with the actual redisplay being the larger part.
But humans are notoriously bad in guessing this stuff, so I won't be
surprised if mine turns out to be wrong.

> there could be some simple cache added on to of it, which would make
> skipping redisplay unnecessary in cases when the command would
> pre-fill such cache.

I have my doubts that it will turn out to be simple.  Besides my
humble experience of hacking the display code, I have a much more
significant evidence: that such a cache was not implemented when the
current display engine was developed for Emacs 21.  Gerd Moellmann is
an extremely capable and talented programmer, and most of the work he
did on the display engine during Emacs 21 development was precisely to
make it fast enough.  All the redisplay optimizations we have now were
designed and implemented for that purpose, because without them
redisplay was unbearably slow on the machines we had at that time.  At
some point Gerd wrote that he implemented these optimizations one by
one, until he got satisfactory redisplay speed.  If there was a simple
way of caching more data to speed this up, I have no doubt we'd have
that already.

Of course, no one is perfect, so it could be that some opportunities
were missed.  Ideas and patches are welcome, together with timings and
profiles to show their utility.



reply via email to

[Prev in Thread] Current Thread [Next in Thread]