From: Konfekt Date: Mon, 16 Dec 2024 20:10:45 +0000 (+0100) Subject: runtime(doc): document how to minimize fold computation costs X-Git-Tag: v9.1.0934~1 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=3920bb4356aa7324a4be1071c87524a2f921d921;p=thirdparty%2Fvim.git runtime(doc): document how to minimize fold computation costs closes: #16224 Signed-off-by: Konfekt Signed-off-by: Christian Brabandt --- diff --git a/runtime/doc/fold.txt b/runtime/doc/fold.txt index b290492050..61f3b67f39 100644 --- a/runtime/doc/fold.txt +++ b/runtime/doc/fold.txt @@ -1,4 +1,4 @@ -*fold.txt* For Vim version 9.1. Last change: 2023 Mar 24 +*fold.txt* For Vim version 9.1. Last change: 2024 Dec 16 VIM REFERENCE MANUAL by Bram Moolenaar @@ -87,9 +87,11 @@ The most efficient is to call a compiled function without arguments: > The function must use v:lnum. See |expr-option-function|. These are the conditions with which the expression is evaluated: + - The current buffer and window are set for the line. - The variable "v:lnum" is set to the line number. -- The result is used for the fold level in this way: + +The result of foldexpr then determines the fold level as follows: value meaning ~ 0 the line is not in a fold 1, 2, .. the line is in a fold with this level @@ -104,6 +106,8 @@ These are the conditions with which the expression is evaluated: "<1", "<2", .. a fold with this level ends at this line ">1", ">2", .. a fold with this level starts at this line +The result values "=", "s" and "a" are more expensive, please see |fold-expr-slow|. + It is not required to mark the start (end) of a fold with ">1" ("<1"), a fold will also start (end) when the fold level is higher (lower) than the fold level of the previous line. @@ -117,12 +121,6 @@ recognized, there is no error message and the fold level will be zero. For debugging the 'debug' option can be set to "msg", the error messages will be visible then. -Note: Since the expression has to be evaluated for every line, this fold -method can be very slow! - -Try to avoid the "=", "a" and "s" return values, since Vim often has to search -backwards for a line for which the fold level is defined. This can be slow. - If the 'foldexpr' expression starts with s: or ||, then it is replaced with the script ID (|local-function|). Examples: > set foldexpr=s:MyFoldExpr() @@ -148,6 +146,36 @@ end in that line. It may happen that folds are not updated properly. You can use |zx| or |zX| to force updating folds. +Minimizing Computational Cost *fold-expr-slow* + +Due to its computational cost, this fold method can make Vim unresponsive, +especially when the fold level of all lines have to be initially computed. +Afterwards, after each change, Vim restricts the computation of foldlevels +to those lines whose fold level was affected by it (and reuses the known +foldlevels of all the others). + +The fold expression should therefore strive to minimize the number of dependent +lines needed for the computation of a given line: For example, try to avoid the +"=", "a" and "s" return values, because these will require the evaluation of the +fold levels on previous lines until an independent fold level is found. + +If this proves difficult, the next best thing could be to cache all fold levels +in a buffer-local variable (b:foldlevels) that is only updated on |b:changedtick|: +>vim + vim9script + def MyFoldFunc(): number + if b:lasttick == b:changedtick + return b:foldlevels[v:lnum - 1] + endif + b:lasttick = b:changedtick + b:foldlevels = [] + # compute foldlevels ... + return b:foldlevels[v:lnum - 1] + enddef + set foldexpr=s:MyFoldFunc() +< +In above example further speedup was gained by using a precompiled Vim9script +function without arguments (that must still use v:lnum). See |expr-option-function|. SYNTAX *fold-syntax* diff --git a/runtime/doc/tags b/runtime/doc/tags index 0f8b2051f4..9f46c6e061 100644 --- a/runtime/doc/tags +++ b/runtime/doc/tags @@ -7218,6 +7218,7 @@ fold-create-marker fold.txt /*fold-create-marker* fold-delete-marker fold.txt /*fold-delete-marker* fold-diff fold.txt /*fold-diff* fold-expr fold.txt /*fold-expr* +fold-expr-slow fold.txt /*fold-expr-slow* fold-foldcolumn fold.txt /*fold-foldcolumn* fold-foldlevel fold.txt /*fold-foldlevel* fold-foldtext fold.txt /*fold-foldtext*