[Top][All Lists]

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

Re: jit-lock refontifies too much

From: martin rudalics
Subject: Re: jit-lock refontifies too much
Date: Sun, 25 Sep 2005 15:17:48 +0200
User-agent: Mozilla Thunderbird 1.0 (Windows/20041206)

Stefan wrote:
> In the above case, the syntax-ppss state changes, so using that would solve
> this problem.  But changing
>         (defvar foo 1
>           "hello")
> to
>         (defvar foo 0 1
>           "hello")
> also requires a similar refontification, but the syntax-ppss state doesn't
> really change, so even using syntax-ppss wouldn't solve this problem.

And that would be a fairly common case too, for example, when mistyping
something on the first line of a definition.  Maybe one day someone
writes a parse-partial-sexp with a return value that holds the number of
elements in the innermost containing list before TO - useful to speed up
lisp-font-lock-syntactic-face-function anyway.  Till then I must remove
any optimizations when paren depth equals/equaled 1 in Lisp modes.

Richard wrote:
>     - Syntactic context is correctly established via the face property
>        assigned to a character by font-lock.  As an example, font-lock
>        assigns a character the font-lock-string-face property iff that
>        character is within a string - according to the best knowledge of
>        syntax-ppss.
> It might be worth doing this for the first character of a line, only.
> That would bound the extent of refontification, but without wasting]
> lots of space for text properties.

I don't waste any text properties on this.  All I do is comparing the
face property of one specific character as assigned by refontification
against the face property of that character before refontification.  If
these two differ I have to refontify subsequent text.  Unfortunately, as
Stefan pointed out, comparing face properties is not sufficient to
detect all possible changes of syntactic context.

> In the code that you wrote, are these properties put on characters at
> the start of a line, or could they appear anywhere?
>     There is one complication: When text has not been fontified yet, the
>     comparison described above would always indicate a context change.
> I do not understand that statement.  When the subsequent text has
> not been fontified yet, it certainly needs to be fontified.
> So what is it that you perceive as a problem?

False positives: When, for example, text within a string was never
fontified before it (usually) does not have a font-lock face property.
After first fontification it does.  Hence my comparison above would
indicate a change although there never was a buffer modification.  Each
time I scrolled backwards into yet unfontified text I would have to
refontify the rest of the buffer.  That's what I needed my text property
for.  The property would have been added together with the fontified nil
property on the entire modified text.  Hence the property could have
appeared anywhere.

> Stefan wrote:
>     Adding yet-another-text-property is a waste of precious CPU and
>     memory resources.  It makes your suggestion pretty dubious.  Luckily, 
>     syntax-ppss instead of faces should not suffer from this same 
>     problem.
> How does syntax-ppss avoid the need to scan too far?
> (I know you told me before, but I don't remember.)
> I wonder if use of syntax-ppss will be faster than
> the refontifications it saves.

syntax-ppss is called in font-lock-fontify-syntactically-region -
usually every time I insert/delete one single character.  Hence it
should be very fast.  In practice it runs parse-partial-sexp from the
beginning of the first line where a buffer modification occurred
recently.  It might be interesting to cache additional values when
typing or inserting longer stretches of text by temporarily binding
syntax-ppss-max-span to something less than the default value.  The
current strategy attempts to distribute cache positions evenly in a
buffer.  However, buffers don't change evenly.

> You wrote:
>     I'm only comparing Emacs-22.1 jit-lock with my patch.  On a 1GHz machine
>     setting jit-lock-context-time to zero seconds makes Emacs stutter when I
>     use auto-repeat to insert a sequence of characters.
> jit-lock-context-time is not normally zero.  So what exactly is the
> goal of your proposal?  Is the goal to make jit-lock-context-time zero
> without loss of performance?

My goal is to save CPU overhead due to contextual refontification.  But
Stefan asked me to provide an example where contextual refontification
could have visible impact.

In practice I wouldn't ever set jit-lock-context-time to zero.  When I
insert, for example, a single string delimiter, I don't want to have all
subsequent lines change their face instantaneously since I usually close
the string immediately afterwards.  Contextual fontification is useful
to remind me when I forget to insert a delimiter or, to tell me that I
have corrected that mistake.  The default value accomplishes this in an
ideal way - to my taste.  In this context it's also important that the
value is larger than the auto-repeat delay of the keyboard.

>      > The above problems can be "easily" addressed by changing your 
algorithm to
>      > not look at the face property, but instead to look at the return value 
>      > syntax-ppss.  If it hasn't changed, then we know the subsequent text 
>      > need refontification.
>      >
>     I don't remember any previous return value when refontifying.  Calling
>     syntax-ppss twice for the same position in one and the same invocation
>     of jit-lock-fontify-now always yields the same value.
>     The property would last only as long as there are unhandled buffer
>     changes.  However, it does waste resources.  Too bad that syntax-ppss
>     won't work.
> I don't understand that response.

As sketched above I try to detect whether syntactic context changes by
comparing two values.  When I compare face properties the old property
is still there before I refontify, maybe some time after the buffer
modification.  I remember the old value, refontify, and compare the old
value against the new value after refontification.  With ppss things are
different since any "old value" gets lost together with the buffer
modification.  Hence, I can't use ppss to establish the old value when

"The property would last ..." sentence refers to the text property I
needed to discriminate regions that were never fontified before from
regions that were refontified due to a buffer change.  The property
would have got removed as soon as all yet unresolved positions had been
either fontified or their fontified property set to nil.  However, till
then it would have wasted resources.

> Stefan wrote:
>     Oh, right, when jit-lock-fontify-now gets called, the buffer is already
>     changed, so you'd have to use a before-change-functions hook to remember 
>     syntax-ppss state before the change.  Hmmm...
> You'd have to cache the syntax-ppss value in a text property, perhaps
> for the first char on a line.

That would be overly expensive.  I rewrote all this with ppss, two
markers, a before-change-functions hook and without any text properties.
It seems to work but needs some further testing.

reply via email to

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