emacs-devel
[Top][All Lists]
Advanced

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

Re: emacs rendering comparisson between emacs23 and emacs26.3


From: Eli Zaretskii
Subject: Re: emacs rendering comparisson between emacs23 and emacs26.3
Date: Tue, 07 Apr 2020 17:26:25 +0300

> Cc: address@hidden, address@hidden, address@hidden, address@hidden,
>  address@hidden
> From: Dmitry Gutov <address@hidden>
> Date: Mon, 6 Apr 2020 20:16:43 +0300
> 
> > What that binding does is affect the portions of display code that are
> > run as part of window_scroll_pixel_based, which the scroll command
> > calls to calculate a suitable position of window-start by simulating
> > display.  That display code runs with fontifications disabled, which
> > makes it faster.
> > 
> > All the scroll commands in Emacs do is more or less calculate the
> > window-start point; the rest is done when redisplay kicks in.
> 
> So what happens then? Does it trigger jit-lock anyway?

Basically, yes.  But with a twist, see below.

> If so, I don't understand how we get the apparent performance improvement 
> from using fast-but-imprecise-scrolling.

To explain that, I need to step back and describe how jit-lock
mechanism works, from the display engine POV, and then how the scroll
commands work.  (See also a large commentary in keyboard.c around line
250.)

For simplicity, let's assume we have a buffer with no overlays, no
display strings, and no other complications, only faces.  Let's also
assume the text is entirely L2R, so we can ignore what bidi.c does.

When the display engine starts working on displaying a window, it
begins from the window-start position, loads all the faces and other
display-related stuff, then starts layout by moving one character at a
time in the direction of increasing buffer positions, and computing
the metrics of each character as determined by the face(s) at each
position.  It stops when it gets to a buffer position where the
'fontified' text property changes its value.  If the new value of
'fontified' is nil, the display engine calls fontification-functions.
jit-lock adds its function to that hook, so jit-lock is called.  What
jit-lock does, in a nutshell, is call the current buffer's
fontification function(s) on a chunk of text starting at the position
for which it was called, and it puts on that chunk a value of t for
the 'fontified' text property.  (Where that chunk ended is the
position where the 'fontified' property's value will again change to
nil, and if that position is inside the window, jit-lock will be
called again when the display engine gets to that position.)  After
fontification-functions return, the display engine processes the faces
in the chunk that has been fontified; then it continues marching
through the buffer.

Next, I need to describe how scroll commands work.  Assuming you typed
C-v, the scroll command computes the new window-start point.  It does
so by beginning at the current window-start, then moving through the
buffer text until it reaches the point that is N pixels down, where N
is the height of the window.  To move through the text, the scroll
command uses functions from the display engine that "simulate"
display, i.e. they perform the same layout calculations, but don't
prepare anything to be sent to the glass.  However -- and this is the
important part -- this "display simulation" uses the same code
described above that looks for positions where the 'fontified'
property is nil and calls fontification-functions to fontify such
text.  This is necessary, because fontification can change the metrics
of the text on display, and so any pixel-wise calculations and
decisions whether given text is or isn't inside a window must be sure
the text is fontified and has the right faces in order to produce
accurate results.

When the scroll command is done computing the new window-start point,
it sets a special flag telling redisplay to obey that window-start
value (otherwise redisplay might decide to compute window-start on its
own), and returns.

Then redisplay kicks in, and does its thing described above.  It will
find the entire text until the new window-start already fontified, and
also some text after the new window-start (because jit-lock works in
chunks, and usually fontifies slightly more than strictly needed).  So
displaying the new contents of the window will need to fontify only
those parts visible in the window that were not already fontified when
the scroll command looked for the new window-start.

If you lean on C-v, then the scroll command is repeatedly called to
find the next window-start, and repeatedly fontifies the text it goes
through.  If you scroll N screen-fulls, the fontification of the first
N-1 screen-fulls (if they were never displayed before, which happens
when you visit a file and immediately start scrolling) is "wasted
effort" for the purposes of the final window redisplay, because those
N-1 screen-fulls will not be displayed.  Only the fontification of the
last screen-full is "useful", because it saves some, sometimes all, of
the fontification job of the stuff to be eventually displayed when you
stop scrolling.

Enter fast-but-imprecise-scrolling.  What it does is disable jit-lock
during the part where the scroll command walked the buffer to find the
next window-start position.  Crucially, it also disables putting the
non-nil 'fontified' property on the text traversed by the scroll
command (because that is done by jit-lock).  So when you stop
scrolling, redisplay of the stuff that ends up in the window will have
to fontify all of what is visible in the window.

Bottom line: fast-but-imprecise-scrolling saves the work of jit-lock
when scrolling more than one screen-full, and is more-or-less useless
when scrolling one screen-full.  IOW, it is a "solution" for the use
case of leaning on C-v or M-v to scroll far into the buffer that was
never before displayed.

Of course, if fast-but-imprecise-scrolling makes the job of scroll
commands so much easier that Emacs is capable of keeping up with the
keyboard auto-repeat rate, then every screen-full you scroll through
_will_ be displayed, and therefore will be fontified by the calls to
jit-lock from redisplay itself -- and that will again make scrolling
slower.  So fast-but-imprecise-scrolling is most efficient when it
makes scroll commands faster, but not too fast...

Sorry for the long email, I hope this tricky issue is now at least a
tad more clear.



reply via email to

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