You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Mass opening/closing files has quadratic slowdown.
Steps to Reproduce the Issue
Open Notepad++
Select 1000 files (typically I search for all *.txt in a folder) and drag + drop them onto Notepad++
Observe Notepad++ sits frozen for some time (varies depending on system)
After they're opened go to file->close-all and observe the same slow time to close
Expected Behavior
At worse case the slowdown should be linear to the number of files opened (or as close to linear as possible within the limits of what it has to do when opening files)
Actual Behavior
Notepad++ sits frozen for some time while it works on the files.
Debug Information
This isn't specific to any Notepad++ version but a general issue that has existed for as long as I've used Notepad++.
I recently decided to profile the code to see what the time got spent on and found several things to improve. My results can be found here: #9036
The 3 things I found:
The cost of DocTabView::getIndexByBuffer(BufferID) is worse-case linear O(N) and is executed several times per file opened and closed and the N being opened file count so as more files are opened the cost of the function grows.
I addressed this by caching the file tab index for a given DocTabView in the Buffer and when the index is requested it first checks if the cached value is correct. If the cached value is correct then the cost is O(1); if the cached value is not correct it falls back to linear-scan to find the real value - to keep behavior correct. The only time(s) that I can think of where a tab index cache may become wrong are tab-reordering (rare), and moving tabs between views (also rare). Additionally when the linear-scan operation runs it updates the cached indexes for every tab it touches so even in the cached-index-is-wrong case it quickly goes back to O(1) cost for future operations.
The cost of LastRecentFileList::updateMenu() is quite high because it erases and refreshes the entire menu. This function is called for every file closed when closing many files (close-all, close-all-but-this and so on). As far as I can tell/test It only needs to get called once after all of the requested files are closed.
I addressed this by doing exactly that: hold refreshing the menu until all of the close operations are done.
When opening a new file the function DocTabView::addBuffer(...) is used to add the GUI tab for the file. However the tab meta-information is provided through calling DocTabView::bufferUpdated(...) instead of being passed during the TCM_INSERTITEM message. This results in having to do an expensive TCM_SETITEM call for every new opened file when the meta information could be passed along with the original add-GUI-tab call.
I addressed this by passing the tab meta information during the insert call.
The remaining time after addressing these 3 points is spent in TCM_INSERTITEM and TCM_DELETEITEM which as far as I can find can't be avoided without switching to an entirely new GUI system (I don't see that happening).
Additional information
Testing 1000 files on my system:
Before: 14.6 seconds to open
Before: 8.2 seconds to close-all
After: 5 seconds to open
After: 3.4 seconds to close-all
The text was updated successfully, but these errors were encountered:
Description of the Issue
Mass opening/closing files has quadratic slowdown.
Steps to Reproduce the Issue
Expected Behavior
At worse case the slowdown should be linear to the number of files opened (or as close to linear as possible within the limits of what it has to do when opening files)
Actual Behavior
Notepad++ sits frozen for some time while it works on the files.
Debug Information
This isn't specific to any Notepad++ version but a general issue that has existed for as long as I've used Notepad++.
I recently decided to profile the code to see what the time got spent on and found several things to improve. My results can be found here: #9036
The 3 things I found:
DocTabView::getIndexByBuffer(BufferID)
is worse-case linear O(N) and is executed several times per file opened and closed and theN
being opened file count so as more files are opened the cost of the function grows.I addressed this by caching the file tab index for a given DocTabView in the Buffer and when the index is requested it first checks if the cached value is correct. If the cached value is correct then the cost is O(1); if the cached value is not correct it falls back to linear-scan to find the real value - to keep behavior correct. The only time(s) that I can think of where a tab index cache may become wrong are tab-reordering (rare), and moving tabs between views (also rare). Additionally when the linear-scan operation runs it updates the cached indexes for every tab it touches so even in the cached-index-is-wrong case it quickly goes back to O(1) cost for future operations.
I addressed this by doing exactly that: hold refreshing the menu until all of the close operations are done.
DocTabView::addBuffer(...)
is used to add the GUI tab for the file. However the tab meta-information is provided through callingDocTabView::bufferUpdated(...)
instead of being passed during the TCM_INSERTITEM message. This results in having to do an expensive TCM_SETITEM call for every new opened file when the meta information could be passed along with the original add-GUI-tab call.I addressed this by passing the tab meta information during the insert call.
The remaining time after addressing these 3 points is spent in TCM_INSERTITEM and TCM_DELETEITEM which as far as I can find can't be avoided without switching to an entirely new GUI system (I don't see that happening).
Additional information
Testing 1000 files on my system:
Before: 14.6 seconds to open
Before: 8.2 seconds to close-all
After: 5 seconds to open
After: 3.4 seconds to close-all
The text was updated successfully, but these errors were encountered: