Styling Speed tied to Visible Area
-
I’m currently using styling outside of a Lexer and have noticed that the speed is highly dependent on the visible area in N++.
When I’m in the middle of the document and begin highlighting each line, the styling speed becomes so slow that it’s almost freezing until it reaches the visible area. From that point, it’s notably much faster. Interestingly,
I can manipulate the speed during the highlighting process by just scrolling up and down. The cursor position doesn’t seem to have any effect on this.
Does anyone have any ideas why this is happening or how to solve?"
I’m defining the styles with these commands:
::SendMessage(_hScintilla, SCI_STYLESETBACK, style, color); ::SendMessage(_hScintilla, SCI_STYLESETFORE, style, fgColor);
I’m highlighting the text with these commands:
::SendMessage(_hScintilla, SCI_STARTSTYLING, start, 0); ::SendMessage(_hScintilla, SCI_SETSTYLING, end - start, style);
-
Perhaps a non-blocking procedure like
::SendMessageTimeout
is what you’re looking for. If I’m reading the documentation correctly, you would want to pass theSMTO_NORMAL
flag so that “[t]he calling thread is not prevented from processing other requests while waiting for the function to return”. -
@rdipardo
I tested it with ::SendMessageTimeout, but no messages seem to be blocking this. However, it didn’t solve the issue.It’s so strange that the speed is significantly affected by the visible area. The performance in the area above is unacceptably slow, and as previously mentioned, I can influence the speed by scrolling up and down even during the styling process.
Additionally, I replaced SendMessage with the command
pSciMsg = (SciFnDirect)::SendMessage(_hScintilla, SCI_GETDIRECTFUNCTION, 0, 0); pSciWndData = (sptr_t)::SendMessage(_hScintilla, SCI_GETDIRECTPOINTER, 0, 0); pSciMsg(pSciWndData, iMessage, wParam, lParam);
For the lower part, this change made things faster, but the upper part is still almost freezing.
Could there possibly be other parameters involved, especially around the first line focus? I find it hard to believe that the performance is solely influenced by the visible area of the document in N++, as evidenced by my tests.
-
@rdipardo said in Styling Speed tied to Visible Area:
Perhaps a non-blocking procedure like
::SendMessageTimeout
is what you’re looking for. If I’m reading the documentation correctly, you would want to pass theSMTO_NORMAL
flag so that “[t]he calling thread is not prevented from processing other requests while waiting for the function to return”.I’m reasonably sure that only applies when the window to which you are sending the message is on a different thread. The SendMessage* commands call the window procedure directly when the window is on the same thread; they only post to the message queue when the thread is different.
There is no way to be “non-blocking” when the function to be called will execute on the same thread as the caller. I believe this is the case with all Scintilla commands. (You could Post instead of Send, but that would only defer the processing until sometime after your function returned.)
-
@Thomas-Knoefel said in Styling Speed tied to Visible Area:
Additionally, I replaced SendMessage with the command
pSciMsg = (SciFnDirect)::SendMessage(_hScintilla, SCI_GETDIRECTFUNCTION, 0, 0); pSciWndData = (sptr_t)::SendMessage(_hScintilla, SCI_GETDIRECTPOINTER, 0, 0); pSciMsg(pSciWndData, iMessage, wParam, lParam);
You might already know this, but just in case you were literally replacing SendMessage with the above: You only need to do SCI_GETDIRECTFUNCTION once, when your plugin is starting up; and you only need to do SCI_GETDIRECTPOINTER once each time you process a call or message (unless you change between primary and secondary Scintilla controls). The expected gain from using the direct function pointer method is in avoiding doing a SendMessage for every call to Scintilla.
-
@Thomas-Knoefel said in Styling Speed tied to Visible Area:
Does anyone have any ideas why this is happening or how to solve?
I’m defining the styles with these commands:
::SendMessage(_hScintilla, SCI_STYLESETBACK, style, color); ::SendMessage(_hScintilla, SCI_STYLESETFORE, style, fgColor);
If the only changes you are making are the foreground and background colors, consider using Indicators instead. I’m using an indicator in a plugin I’m developing and applying and removing it, even over large areas, is virtually instant.
As of Notepad++ version 8.5.6, there is a new NPPM_ALLOCATEINDICATOR message which plugins should use to obtain one or more indicator numbers. It works exactly like NPPM_ALLOCATEMARKER.
-
@Coises said in Styling Speed tied to Visible Area:
If the only changes you are making are the foreground and background colors, consider using Indicators
My further tests are showing me that:I previously started with Indicators (of Scintilla, not NPPM_ALLOCATEMARKER), but they are slower in highlighting. Styles are much faster, as I recognized. But if I hadn’t found any solution, I would have had to switch back to Indicators.
Some points of my further tests:
- The direction in which you’re styling the rows, even when considering the view area, doesn’t affect the speed. The upper section remains always significantly slower.
- I tested SCI_SETBUFFEREDDRAW and SCI_SETREADONLY. with no success
- BUT then I realized that
ShowWindow(_hScintilla, SW_HIDE)
will give a continuous speed for all lines.
So, a combination of SW_HIDE and disabling the N++ window during that period is crucial, as any resizing would instantly revert Scintilla to SW_SHOW.
HWND hMainWnd = ::GetParent(_hScintilla); ::EnableWindow(hMainWnd, FALSE); ShowWindow(_hScintilla, SW_HIDE);
-
Have you checked whether setting different options for SCI_SETIDLESTYLING makes any difference?
-
@Coises said in Styling Speed tied to Visible Area:
Have you checked whether setting different options for SCI_SETIDLESTYLING makes any difference?
I tested them right now, and they make no difference. They seem to be more tied to a direct lexer implementation, as they control the threads for styling.