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

slowdown #238

Closed
marilmanen opened this issue Jan 2, 2021 · 20 comments
Closed

slowdown #238

marilmanen opened this issue Jan 2, 2021 · 20 comments
Labels
performance Technically works, but not efficiently enough

Comments

@marilmanen
Copy link
Contributor

This is an issue that has been causing minor issues for a long time.
I have now been editing some files heavily during past days. Selecting text, changing tabs etc are working a bit slower all the time. It feels like a network latency, but it's not caused be my network connection although I'm running nedit in a remote desktop. Here is what "top" is showing for the process

   VIRT    RES    SHR S  %CPU %MEM     TIME+ COMMAND                                                                                            
2800444   1.8g  39140 S   5.9  1.4 260:55.13 nedit-ng             

First I opened the same files in a new nedit-ng session to see if the issue is related to my network connection or the server performance, but with the new nedit-ng the speed is ok with the same files so it's clearly related to the nedit-ng process. Next I tried File/Revert to Saved to all the files that I had open in the slow nedit-ng session as I thought that the issue might be related to the Undo buffer, but it had no impact. Then I opened two new Untitled tabs and closed all the files I had modified but even that had no impact to the speed issue as tab change between Untitled and Untitled_1 is still slow. It looks like nedit-ng just becomes slow during time and the only workaround is to open the files in a new nedit-ng window.

@eteran eteran added the performance Technically works, but not efficiently enough label Jan 2, 2021
@eteran
Copy link
Owner

eteran commented Jan 2, 2021

Hmm, well 1.8g resident is an awful lot of RAM to be using so I imagine that's a factor at play. I would also guess that the usage creeps up over time as your instance was open for over 10 days.

I'll investigate any memory leaks for sure, but also, can you speak to how large the files you are editing are (on average, no need to be precise). Would you say that your typical working set is on the order of 100's of MB between all of your open files?

@eteran
Copy link
Owner

eteran commented Jan 2, 2021

Also, can you say if you are doing a release, debug, or Release with debug info build? It should default to a RelWithDebInfo and if you're using a Debug build, I'd expect a HUGE performance hit.

@marilmanen
Copy link
Contributor Author

I have been working with small text files, average size in less than 10 kilobytes so the total amount of data in the open files at any time has most likely been less than 10Mbytes. Ending up to 1.8G process size is a mystery for me. The host I'm using has >100G free RAM, so I'm not expecting any issues from that part.
I have not used any options for the build.

@eteran
Copy link
Owner

eteran commented Jan 2, 2021

Well that makes for an interesting mystery indeed!

Ok, well I'll be investigating this, but I do worry that it'll be particularly tough to track down.

Please do occasionally sync up with the master branch just in case I "accidentally fix it" in an unrelated patch though 😜

@marilmanen
Copy link
Contributor Author

I updated to latest version and opened couple small files. While keeping "top" running I just switched between tabs and each tab change increases the process size so at least that's one odd way to increase the process size.

@eteran
Copy link
Owner

eteran commented Jan 2, 2021

Interesting, I did the same and it does indeed very slowly creep up. There are no meaningful explicit allocations happening during a tab focus change, but I'll see if there is something I'm doing that has the side effect of an allocation.

You continue to be excellent at finding these unusual quirks! Thanks for your help :-).

@eteran
Copy link
Owner

eteran commented Jan 3, 2021

As a following, I have a test methodology at the moment. I open up about 6-10 tabs, note the memory usage, and then hold down Ctrl+PageDown (which will CONSTANTLY switch to the "next" tab). When I do this, memory usage does slowly creep up. It's not a huge effect, but the fact that I'm switching probably 20+ times a second makes it visible.

base on this test, I have narrowed down the suspected leak to a few specific function calls... I think. So hopefully, I'll have a nice solution for this.

It may in the end be a "soft leak" where the memory isn't lost and will get deleted before closing the application... but at the same time has something keeping it alive much longer than needed. We'll see.

@tksoh
Copy link
Contributor

tksoh commented Jan 3, 2021

Just wondering, those nice tools out there for detecting memory leak couldn't find the leak?

@eteran
Copy link
Owner

eteran commented Jan 3, 2021

Sadly, I did try those, but I ran into a wall.

Basically, valgrind is the main tool I would use, but my system Qt is compiled with SSE4 enabled, and valgrind simply doesn't support it.

So I could use valgrind, but only if I custom compiles a less optimized version of Qt, and link to that (or wait till valgrind adds support for the few instructions more it needs). But it would be a lot of time and effort to get it going.

I did enable clang's built in memory sanitizer stuff, but it found nothing.

In fact, I'm not even sure valgrind would find this either because it appears to be a "soft-leak", and valgrind only reports memory that is NEVER freed, even on application close. This is looking like a case of "is freed, but not at a reasonable time, instead is only upon application closing". Which is harder to find with tooling.

@eteran
Copy link
Owner

eteran commented Jan 3, 2021

OK! I think I know what the issue is (at least when switching tabs).

For those curious, it's in MainWindow::updateUserMenus, which every time a tab is switched, ensures that all of the custom menus show the right things. This is a fairly dynamic process because things like language modes can effect which menu items are present.

I believe that because this is creating action items, it is slowly using memory each time it is called. The previous versions of these menus may not be able to be triggered, but they are also not explicitly deleted. They are left for Qt to decide when to delete them (which is almost always "when the parent window is destroyed").

If I rework this function to clean up better, I think this particular leak goes away!

eteran added a commit that referenced this issue Jan 3, 2021
I'd like to come up with a more smart pointer based fix, but this
looks correct to me in my tests. We can always refactor it in the future.
eteran added a commit that referenced this issue Jan 3, 2021
I'd like to come up with a more smart pointer based fix, but this
looks correct to me in my tests. We can always refactor it in the future.
@eteran
Copy link
Owner

eteran commented Jan 3, 2021

@marilmanen Please try the new master and let me know if this issue continues :-)

@marilmanen
Copy link
Contributor Author

I updated to version 7559876 and did the Ctrl+PageDown test with two empty files Untitled and Untitled_1. Initial process size was 48k and when the process CPU time hit 30s I stopped the test. CPU load was ~100% during the test so something heavy is ongoing there. Now the process size is

PR  NI    VIRT    RES    SHR S  %CPU %MEM     TIME+ COMMAND
20   0 1302536 580516  32324 S  81.8  0.4   0:32.97 nedit-ng

I repeated the same test with version a8e46e4 and got practically the same result, so I'm confused. I do have a a lot of macros, some new language types and some customizations to existing language types so here is my ~/.config/nedit-ng directory listing

 1824 Jan  3 07:01 autoload.nm
 1942 Jan  3 07:01 config.ini
  579 Mar 26  2020 config_user.ini
17796 Jan  3 07:01 context.yaml
 1774 Jan  3 06:56 history
   91 Jan  3 07:01 indent.yaml
 2535 Jan  3 07:01 languages.yaml
72991 Jan  3 07:01 macros.yaml
 9327 Jan  3 07:01 patterns.yaml
  827 Jan  3 07:01 shell.yaml
 2346 Jan  3 07:01 theme.xml

I tested also with old nedit, but with it it would take a lot of time to reach 30 second CPU time as CPU load was at about 5% . I stopped at CPU time 6 seconds and the process size was the same 9k as it was at the beginning.

@marilmanen
Copy link
Contributor Author

One more strange thing happened with the latest version. I have lost some items in the macro drop-down. "Complete Word" "Fill Sel w/Char", "Quote Mail Reply" and "Unquote Mail Reply" do not exist anymore. I don't mind losing some of them but and I'm so heavy "Fill Sel w/Char" user that I have attached shortcut Alt+U for it in my config files.

@eteran
Copy link
Owner

eteran commented Jan 3, 2021

Sorry!

OK, @tksoh reported the same thing. So my "fix" seems to have a bad side effect of removing macros. I believe that thewy won't be removed from the actual config files. So bear with me as I look into this.

@eteran
Copy link
Owner

eteran commented Jan 3, 2021

@marilmanen @tksoh

OK, I just pushed a fix for the disappearing menu issue. I think it's correct and doesn't display the issue locally Anymore.

@marilmanen You can expect that switching tabs CONSTANTLY will cause high CPU usage as you are asking it to do constant work. It is repeatedly tearing down and recreating the custom menus which won't be "free".

For me, 6 empty tabs idles like this:

  PID USER      PR  NI    VIRT    RES    SHR S  %CPU  %MEM     TIME+ COMMAND
19523 eteran    20   0  336240  78928  61756 S   0.0   0.2   0:00.19 nedit-ng

When doing the test, memory usage did bump up a little bit, but it wasn't runaway growth anymore. I think the increase is possibly due to heap fragmentation or similar because we are basically doing non-stop malloc/free's. I'm going to look into if there is a way to make this function more lazy though.

@eteran
Copy link
Owner

eteran commented Jan 3, 2021

@marilmanen Another small improvement to this operation. Since you've got a lot of macros, presumably in sub-menus, this latest fix may help things for you a bit.

@eteran
Copy link
Owner

eteran commented Jan 3, 2021

Update, I was accidentally testing with the version built with address sanitizer. Now when I do the untitled tab cycle test, memory usage doesn't budge at all.

So I believe that if it is still moving up for you, that the particular macros you have are a factor.

Would you be willing to share a tgz of your config directory for me to try to reproduce locally?

@marilmanen
Copy link
Contributor Author

I updated to the latest version and I think you have solved the issue. Process size is not increasing anymore and as a side effect also the CPU load remains at ~20% during the Ctrl+PageDown test. I'll continue working with this version and let you know in case I notice the slowness again, but typically slowness detection has required several day's of work....

@eteran
Copy link
Owner

eteran commented Jan 3, 2021

Thanks!

@eteran
Copy link
Owner

eteran commented Jan 3, 2021

OK, closing this because the specific issue of memory usage climbing over time due to tab switching has been addressed. Please open a new issue if the slowdown persists and we'll investigate it if/when it happens :-).

@eteran eteran closed this as completed Jan 3, 2021
1div0 pushed a commit to 1div0/nedit-ng that referenced this issue Mar 24, 2021
…teran#245)

I'd like to come up with a more smart pointer based fix, but this
looks correct to me in my tests. We can always refactor it in the future.
1div0 pushed a commit to 1div0/nedit-ng that referenced this issue Mar 24, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
performance Technically works, but not efficiently enough
Projects
None yet
Development

No branches or pull requests

3 participants