You should produce a profile showing in which functions the time is spent.
There has been an optimization to folding with [4f6cd7] that avoids styling text. Its possible that this causes unexpected behaviour. You could revert to before this change to discover if it is the problem.
More generally, try to find the change set where the issue starts occurring, perhaps by using hg bisect.
That likely means its performing multiple small lexings instead of one big one. The trade-offs between different ways of lexing the document can be complex with different strategies performing better in different circumstances. There could be a call to SCI_COLOURISE(SCI_GETENDSTYLED(), -1) before folding.
Thank you for looking into it.
My old implementation is surely not optimised.
But even I use _scintView.execute(SCI_TOGGLEFOLD, 0);
instead of _scintView.collapse(searchHeaderLevel - SC_FOLDLEVELBASE, fold_collapse);
The result in release delay about 1-3 seconds, in debug mode is about 6-9 seconds (on a gamer PC)
Last edit: Don HO 2022-07-02
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
I'm not really seeing a good reason for a performance problem here. A profile may reveal the root cause. Scroll bar changes can slow down bulk operations (the referenced issue doesn't say how many lines are involved) and this can sometimes be improved since Scintilla 5.1.1 by turning off redraw (WM_SETREDRAW) for the operation.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Test toggle all folds speed for following 6MB html file (with syntax highlighting) : SciTE > Notepad2 > notepad++, and notepad++ 8.4.2 become unresponsive on my system. https://github.com/whatwg/html/blob/main/source (download and save as html).
Last edit: Zufu Liu 2022-07-02
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
There are various possibilities involving lexing the lines in the buffer in a way that is costly, particularly if the lexer isn't optimized for incremental use. If a lexer seeks back to the beginning of the buffer or to a header before doing its work then it is going to see poor performance if it is called repeatedly.
A profile can answer questions about what is occurring: maybe its the scroll bar, maybe its repeated redraws, maybe its lexing.
I recall Notepad++ has a second layer of folding for hiding lines. Perhaps this is interacting poorly with some changes made in Scintilla 5.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
it turns out the performance bottleneck is Document::GetLastChild() and ContractionState<LINE>::SetVisible().
After the document is full styled, comment out EnsureStyledTo(LineStart(lineMaxSubord + 2)); makes fold all levels 2x faster on my system, attached the change for Document::GetLastChild(), changed the code to style on demand to avoid unneeded call to LineStart().
LineStart is low cost compared to lexing and is unlikely to be significant - lexers often call several similar complexity methods for each line.
The GetLastChild.cxx change performs lexing in batches of 2 lines instead of line by line. The SciLineFromPosition can be removed - although this can end up with lineEndStyled past the end.
Thus the lexer initialization and finalization costs are halved and are likely dominating. If lexing 2 lines at at time is better then some greater factor may be worthwhile but there will be a trade-off here when the extra lines do not need to be lexed.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
I think this change is enough, my original purpose is to prevent exponential call toEnsureStyledTo(LineStart(lineMaxSubord + 2)) even if the document is whole styled. e.g. application like Notepad++ or old Notepad2 that uses SCI_TOGGLEFOLD or SCI_FOLDLINE to implement custom folding (especially fold all, which calls Editor::FoldLine() on every header line).
Last edit: Zufu Liu 2022-07-06
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
This is also changing the behaviour to style in 2 line blocks which isn't obvious. I'm concerned that lines are being treated unevenly with different lines having different amounts of styling performed. Is fold data discovered as accurately as before or could there be issues with some folders?
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
EnsureStyledTo(LineStart(lineMaxSubord + 2)); is to ensure line lineMaxSubord + 1, aka next line is styled.
This does not change the behavior, it just avoided the call when next line is already styled.
it's lineMaxSubord + 1 > lineEndStyled in the GetLastChild.cpp file, converted to lineMaxSubord >= lineEndStyled to avoid extra addition.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
I didn't respond before since the unedited comment which I saw in an email was different.
While no line will (eventually) be skipped, the point at which the level is read may see different data.
Using this 10-byte text "{\r\n\r\n\r\n}\r\n":
{}
Placing tracepoints:
In EnsureStyledTo as Styling to {pos}
On instance->Lex in LexInterface::Colouriseas Lex {start} {len}
In GetFoldLevel as GetFoldLevel {line}.
Forcing endStyled back to 0 before starting.
Running current release:
Styling to 5
Lex 0 5
GetFoldLevel 1
Styling to 7
Lex 5 2
GetFoldLevel 2
Styling to 10
Lex 7 3
GetFoldLevel 3
GetFoldLevel 4
GetFoldLevel 5
So, the patched code is checking line 2 when 5 bytes (2 lines "{\r\n\r\n") have been lexed but the original code had 7 bytes lexed (3 lines "{\r\n\r\n\r\n").
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
The performance for SetVisible() can be solved by avoid repeated hiding children lines when current header line is already hided (hided by folding it's parent level) with following changes in Editor::FoldLine() and Editor::FoldAll():
The line in question doesn't appear to be directly calling Scintilla so its difficult to know what to examine.
You should produce a profile showing in which functions the time is spent.
There has been an optimization to folding with [4f6cd7] that avoids styling text. Its possible that this causes unexpected behaviour. You could revert to before this change to discover if it is the problem.
More generally, try to find the change set where the issue starts occurring, perhaps by using hg bisect.
Related
Commit: [4f6cd7]
@nyamatongwe,
Thank you for looking into it and replying.
Commit: [4f6cd7] seems to be related.
I've asked Don to join this discussion.
https://github.com/notepad-plus-plus/notepad-plus-plus/issues/11814#issuecomment-1172779922
Related
Commit: [4f6cd7]
That likely means its performing multiple small lexings instead of one big one. The trade-offs between different ways of lexing the document can be complex with different strategies performing better in different circumstances. There could be a call to
SCI_COLOURISE(SCI_GETENDSTYLED(), -1)before folding.Related
Commit: [4f6cd7]
Hi Neil
Thank you for looking into it.
My old implementation is surely not optimised.
But even I use
_scintView.execute(SCI_TOGGLEFOLD, 0);
instead of
_scintView.collapse(searchHeaderLevel - SC_FOLDLEVELBASE, fold_collapse);
The result in release delay about 1-3 seconds, in debug mode is about 6-9 seconds (on a gamer PC)
Last edit: Don HO 2022-07-02
I'm not really seeing a good reason for a performance problem here. A profile may reveal the root cause. Scroll bar changes can slow down bulk operations (the referenced issue doesn't say how many lines are involved) and this can sometimes be improved since Scintilla 5.1.1 by turning off redraw (
WM_SETREDRAW) for the operation.The exact Steps to Reproduce the Issue are in https://github.com/notepad-plus-plus/notepad-plus-plus/issues/11814#issue-1275338700
I hope Don would look into it and continue the discussion.
Thanks again for your helpful replies.
Test toggle all folds speed for following 6MB html file (with syntax highlighting) : SciTE > Notepad2 > notepad++, and notepad++ 8.4.2 become unresponsive on my system.
https://github.com/whatwg/html/blob/main/source (download and save as html).
Last edit: Zufu Liu 2022-07-02
There are various possibilities involving lexing the lines in the buffer in a way that is costly, particularly if the lexer isn't optimized for incremental use. If a lexer seeks back to the beginning of the buffer or to a header before doing its work then it is going to see poor performance if it is called repeatedly.
A profile can answer questions about what is occurring: maybe its the scroll bar, maybe its repeated redraws, maybe its lexing.
I recall Notepad++ has a second layer of folding for hiding lines. Perhaps this is interacting poorly with some changes made in Scintilla 5.
it turns out the performance bottleneck is
Document::GetLastChild()andContractionState<LINE>::SetVisible().After the document is full styled, comment out
EnsureStyledTo(LineStart(lineMaxSubord + 2));makes fold all levels 2x faster on my system, attached the change forDocument::GetLastChild(), changed the code to style on demand to avoid unneeded call toLineStart().Last edit: Zufu Liu 2022-07-03
LineStartis low cost compared to lexing and is unlikely to be significant - lexers often call several similar complexity methods for each line.The
GetLastChild.cxxchange performs lexing in batches of 2 lines instead of line by line. TheSciLineFromPositioncan be removed - although this can end up withlineEndStyledpast the end.Thus the lexer initialization and finalization costs are halved and are likely dominating. If lexing 2 lines at at time is better then some greater factor may be worthwhile but there will be a trade-off here when the extra lines do not need to be lexed.
Something used by idle styling? e.g.
LineFromPositionAfter()2 or more lines estimated with a small duration?SciLineFromPositionis needed for Notepad++'s buggy LexSearchResult.cxx , under some condition it does nothing (no update toendStyled).https://github.com/notepad-plus-plus/notepad-plus-plus/blob/master/lexilla/lexers/LexSearchResult.cxx#L116
Looks like it needs a
Flush().LexSearchResult should be fixed - this shouldn't be covered up by Scintilla.
I think this change is enough, my original purpose is to prevent exponential call to
EnsureStyledTo(LineStart(lineMaxSubord + 2))even if the document is whole styled. e.g. application like Notepad++ or old Notepad2 that usesSCI_TOGGLEFOLDorSCI_FOLDLINEto implement custom folding (especially fold all, which callsEditor::FoldLine()on every header line).Last edit: Zufu Liu 2022-07-06
This is also changing the behaviour to style in 2 line blocks which isn't obvious. I'm concerned that lines are being treated unevenly with different lines having different amounts of styling performed. Is fold data discovered as accurately as before or could there be issues with some folders?
EnsureStyledTo(LineStart(lineMaxSubord + 2));is to ensure linelineMaxSubord + 1, aka next line is styled.This does not change the behavior, it just avoided the call when next line is already styled.
it's
lineMaxSubord + 1 > lineEndStyledin the GetLastChild.cpp file, converted tolineMaxSubord >= lineEndStyledto avoid extra addition.The
EnsureStyledTodoes the same work as before when called but is only called for half the lines.The code is correct, no line will be skipped
as
EnsureStyledTo()is doingLast edit: Zufu Liu 2022-07-07
I didn't respond before since the unedited comment which I saw in an email was different.
While no line will (eventually) be skipped, the point at which the level is read may see different data.
Using this 10-byte text "{\r\n\r\n\r\n}\r\n":
Placing tracepoints:
In EnsureStyledTo as
Styling to {pos}On
instance->LexinLexInterface::ColouriseasLex {start} {len}In GetFoldLevel as
GetFoldLevel {line}.Forcing endStyled back to 0 before starting.
Running current release:
Running patched code:
So, the patched code is checking line 2 when 5 bytes (2 lines "{\r\n\r\n") have been lexed but the original code had 7 bytes lexed (3 lines "{\r\n\r\n\r\n").
Seems to me the patch avoid a lex for line 2 as the whole line (first 5 bytes) already lexed?
I just realized two or more lines need to be styled in
EnsureStyledTo()as some lexer (e.g. LexDiff) may change fold level for previous line.Oh, I'm wrong, on
GetFoldLevel 2, line 3 is not yet lexed.The performance for
SetVisible()can be solved by avoid repeated hiding children lines when current header line is already hided (hided by folding it's parent level) with following changes inEditor::FoldLine()andEditor::FoldAll():I'd leave this to the Notepad++ developers to see if it makes a significant difference. It appears to me that it will only have a minor effect.