Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Mass opening/closing files has quadratic slowdown. #9035

Open
Rseding91 opened this issue Oct 19, 2020 · 1 comment
Open

Mass opening/closing files has quadratic slowdown. #9035

Rseding91 opened this issue Oct 19, 2020 · 1 comment

Comments

@Rseding91
Copy link

Rseding91 commented Oct 19, 2020

Description of the Issue

Mass opening/closing files has quadratic slowdown.

Steps to Reproduce the Issue

  1. Open Notepad++
  2. Select 1000 files (typically I search for all *.txt in a folder) and drag + drop them onto Notepad++
  3. Observe Notepad++ sits frozen for some time (varies depending on system)
  4. 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

@ArkadiuszMichalski
Copy link
Contributor

I check your fix on my setup and get this result (32-bit NPP):

  • 897 txt files:
    Before: 12s open and 7s close
    After: 6s open and 3s close

  • 1120 HTML files:
    Before: 20s open and 10s close
    After: 11s open and 6s close

  • 3191 mixed (js/json/md...) from Node modules:
    Before: 110s open and 67s close
    After: 50s open and 43s close

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants