[Linux] Very high memory usage
I'm not sure if it's been reported before, but WTQ running in Linux (Fedora KDE 43 and before) uses up like 700MB-1GB of RAM.
@nabaxo Thank you for reporting this!
Could you share your settings file?
Also, what installation method are you using?
Here's my settings:
{
"$schema": "wtq.schema.json",
"Apps": [
{
"Name": "Wezterm",
"Hotkeys": [
{
"Modifiers": "Super",
"KeyChar": "`"
},
{
"Modifiers": "Super",
"KeyChar": "Β§"
}
],
"FileName": "wezterm-gui",
"Arguments": "start --class=wezquake",
"ProcessName": "wezquake"
}
],
"AnimationTargetFps": 120,
"HideOnFocusLost": "Never",
"HorizontalScreenCoverage": 40,
"VerticalScreenCoverage": 40,
"AnimationDurationMs": 350,
"AnimationTypeToggleOn": "EaseOutCubic",
"AnimationTypeToggleOff": "EaseInQuart"
}
I installed with the script I think.
At the moment it's "only" using 300mb though. But that's still quite a lot.
Way too much, totally agree.
Seems to be some weird stuff going on somewhere, need to try and find out where all this unmanaged memory is coming from:
Some observations so far:
- (Part of it) may be Linux-specific, use quickly grows to 300-400MB+, whereas on Windows generally usage hovers around 60-100MB. Found these issues that may or may not be relevant [1]
- The native dependencies (such as webkit for the GUI) seem to have some part in it, as a big chunk of the unmanaged memory is allocated right from the start (like ~300-400MB), which doesn't happen when disabling these components
- There are definitely areas in the code that can use some optimization or reconsideration, like not having the gui running all the time, and the log window
- There seems to also be some longer-term component going on, where after the initial 400MB chunk, memory can grow to over a gig. Not sure if that's coming from the managed or unmanaged part.
[1]
- https://github.com/dotnet/runtime/issues/95922
- https://github.com/dotnet/runtime/issues/96091
@nabaxo Are you in a position where you could make memory dumps, e.g. with dotnet-dump?
With instructions, I could provide the memory dumps.
I'd like to scope this issue to the scenario where memory balloons from ~300MB to 700-1000. It seems (for me at least) that generally, the memory usage on Linux is hovering around 300MB, but in some cases can blow up to about 1GB.
I do think that 300MB is still a bit much, but current observations suggest that that can be a stable operating usage, whereas increases to 1GB are more exceptional.
If you're up for it, you could make a dump (teehee) when this happens, with these steps:
- Have .Net 9 installed
- Install the "dotnet-dump" tool:
dotnet tool install --global dotnet-dump - When memory is particularly high, dump wtq's core:
dotnet-dump collect -n wtq
The .NET 9, is that the dotnet-sdk? I'm just looking to install it easily on my distro.
The .NET 9, is that the dotnet-sdk? I'm just looking to install it easily on my distro.
Yes!
Uh, running dotnet-dump collect -n wtq dumped a 70GB file on my disk.
How do you want the dump then? It's still there.
How do you want the dump then? It's still there.
I'll get back to you, also got a massive memory dump myself, kinda weird.
One way to get a high-level view of what's going on, is by dumping the virtual memory mapping:
pmap -x $(ps -C wtq -o pid=) > vmem.txt
The "ps" part pulls out the wtq process id, which is then fed into "pmap", which dumps a list of memory regions.
If you could paste that here, or as an attachment, we could get a first look at where the memory is going.
On my machine, what I'm seeing is a bunch of memory coming from native libraries, that are usually not mapped into physical memory, but when they do, increase usage to the earlier seen 700-800MB.
Much of these seem to relate to the GUI, so I'd like to track memory usage on a headless build of wtq, see if where it maxes out on.
Here are some of the larger modules loaded in, with some parts swapped out:
Here is the total of all modules, full size (~700MB):
Here's the resident parts, i.e. the actually loaded in parts ~137MB:
Both screenshots have excluded the runtime memory allocated by the CLR, which show up as "[ anon ]".
So my hypothesis is that the difference we're seeing is mostly in native libraries, not necessarily incredibly inefficient use by the app itself, or memory leaks.
Hopefully a headless build could shed some light on that.
@nabaxo Assuming most of the memory usage does indeed come from the GUI-related libraries, can you tell me your use of the GUI? I.e., what are your thoughts on making the GUI a setting, or maybe even a separate executable or something?
Additionally, I've added a prerelease that disables the GUI entirely (aside from the tray icon, if you count that as "GUI").
Are you willing to test drive that for a bit, see what happens to the memory usage?
The release also switches to "Invariant Mode", which removes another ~20MB-30MB from the heap.
As for your first question, here's the dump. vmem.txt
As for the second, I personally just use the JSON, but the GUI is a useful option. It is absolutely necessary for most regular users though. Maybe make the GUI standalone.
Anyway, taking the pre-release for a spin and see how that works out!
Quick update, it still uses ~500mb.
Here's the new vmem-dump:
Thank you for taking the effort!
I'm confused at the result though, as this seems to indicate ~150MB:
How are you determining the memory, i.e. what is saying 500MB?
Here's what system monitor is saying:
And here's what Mission Center is saying:
What the hell π
What does this show?
ps -u -p $(ps -C wtq -o pid=)
Running this prerelease hasn't cracked 70MB on my machine, the plot thickens!
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
marco 389188 0.9 0.0 276392352 63868 ? Ssl Nov23 26:59 /home/marco/.local/share/wtq/wtq
^^^^^ ~64MB
Here you go!
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
nabaxo 2903 0.3 0.2 276515128 147820 ? Ssl Nov24 4:05 /home/nabaxo/.local/share/wtq/wtq
Okay, I'm still reading up on how to actually interpret all these numbers, but couple points meanwhile.
Recognizing that memory usage is not as simple as it may sound, one thing kinda wild is how much different applications can differ in their memory reporting.
Here's a VM with Fedora 43 KDE, with KDE System Monitor and Mission Center:
That's running the Flatpak version of Mission Center, is that the one you also use, or are you using it through Copr or something? It's the stable release of WTQ, with full GUI. So this does come quite close to the numbers you're seeing, at least on the Mission Center side.
Could you show the output of this:
cat /proc/$(pidof -s wtq)/smaps_rollup
Also, not to be that guy, but are you sure the last numbers are from the headless pre-release?
As a test, the version should say "2.0.19", and clicking "Open Main Window" should do nothing.
Here's the output:
β°β cat /proc/$(pidof -s wtq)/smaps_rollup
55a75a36c000-7fffbb039000 ---p 00000000 00:00 0 [rollup]
Rss: 150460 kB
Pss: 121695 kB
Pss_Dirty: 69384 kB
Pss_Anon: 43764 kB
Pss_File: 52243 kB
Pss_Shmem: 25688 kB
Shared_Clean: 36416 kB
Shared_Dirty: 24 kB
Private_Clean: 44648 kB
Private_Dirty: 69372 kB
Referenced: 150460 kB
Anonymous: 43764 kB
KSM: 0 kB
LazyFree: 0 kB
AnonHugePages: 0 kB
ShmemPmdMapped: 0 kB
FilePmdMapped: 0 kB
Shared_Hugetlb: 0 kB
Private_Hugetlb: 0 kB
Swap: 0 kB
SwapPss: 0 kB
Locked: 0 kB
I am indeed running the version:
Then when it comes to mission center, I am running the flatpak version. But ever since an update on dotnet-9, this is what mission center reports:
And this is what System Monitor reports:
More questions π
Are you running the framework-dependent, or the self-contained version?
Also, I'm seeing weird stuff, here's the alleged usage from the overview screen in KDE System Monitor:
And here's the one in the process detail tab:
The smaps rollup tells me this:
558459dbe000-7ffed9f23000 ---p 00000000 00:00 0 [rollup]
Rss: 148128 kB
Pss: 114818 kB
Pss_Dirty: 67256 kB
Pss_Anon: 46056 kB
Pss_File: 47457 kB
Pss_Shmem: 21304 kB
Shared_Clean: 41372 kB
Shared_Dirty: 28 kB
Private_Clean: 39484 kB
Private_Dirty: 67244 kB
Referenced: 122876 kB
Anonymous: 46056 kB
KSM: 0 kB
LazyFree: 0 kB
AnonHugePages: 28672 kB
ShmemPmdMapped: 0 kB
FilePmdMapped: 12288 kB
Shared_Hugetlb: 0 kB
Private_Hugetlb: 0 kB
Swap: 18556 kB
SwapPss: 10088 kB
Locked: 0 kB
A factor that I didn't consider before, depending on the particular metric, any child processes could be taken into account when calculating the memory usage.
Since apps can be started from WTQ, this means that a system monitor app sees WTQ as its parent process, and may take the child process into account as part of WTQ's memory.
Here's a breakdown of my current process tree (all RSS):
wtq(3089) 146MB
-dolphin(3275) 222MB
-keepassxc(3322) 210MB
-plasma-systemmo(3300) 360MB
-vesktop(1352300) 1500MB
-wezterm-gui(3159) 480MB
----------------------------------------------
~2900MB
The combined usage approaches the KDE System Monitor overview's reported usage:
So could you take a look at the process tree, starting at WTQ's process:
pstree -p $(pidof wtq)
You can also use something like htop for that, or do it straight from System Monitor even:
This may solve part of the problem, i.e., tell us that we can trust the ~150MB figure that seems to come back from multiple apps.
I'm using the self-contained version, here's the output of pstree -p $(pidof wtq):
wtq(2772)ββ¬βwezterm-gui(3100)ββ¬βzsh(3169)βββpstree(23015)
β ββ{wezterm-gui}(3112)
β ββ{wezterm-gui}(3133)
β ββ{wezterm-gui}(3145)
β ββ{wezterm-gui}(3146)
β ββ{wezterm-gui}(3147)
β ββ{wezterm-gui}(3160)
β ββ{wezterm-gui}(3170)
β ββ{wezterm-gui}(3171)
β ββ{wezterm-gui}(3172)
β ββ{wezterm-gui}(3173)
β ββ{wezterm-gui}(3210)
β ββ{wezterm-gui}(3320)
β ββ{wezterm-gui}(3321)
β ββ{wezterm-gui}(3328)
β ββ{wezterm-gui}(3329)
β ββ{wezterm-gui}(3340)
β ββ{wezterm-gui}(3396)
β ββ{wezterm-gui}(3413)
ββ{wtq}(2816)
ββ{wtq}(2817)
ββ{wtq}(2819)
ββ{wtq}(2820)
ββ{wtq}(2822)
ββ{wtq}(2823)
ββ{wtq}(2824)
ββ{wtq}(2825)
ββ{wtq}(2826)
ββ{wtq}(2827)
ββ{wtq}(2828)
ββ{wtq}(2829)
ββ{wtq}(2830)
ββ{wtq}(2831)
ββ{wtq}(2832)
ββ{wtq}(2833)
ββ{wtq}(2834)
ββ{wtq}(2835)
ββ{wtq}(2837)
ββ{wtq}(2840)
ββ{wtq}(2841)
ββ{wtq}(2842)
ββ{wtq}(2843)
ββ{wtq}(2844)
ββ{wtq}(2845)
ββ{wtq}(2846)
ββ{wtq}(2847)
ββ{wtq}(2848)
ββ{wtq}(2855)
ββ{wtq}(2907)
ββ{wtq}(3002)
ββ{wtq}(3062)
ββ{wtq}(3063)
ββ{wtq}(3064)
ββ{wtq}(3065)
ββ{wtq}(3078)
ββ{wtq}(3080)
ββ{wtq}(3084)
ββ{wtq}(21709)
ββ{wtq}(22012)
ββ{wtq}(22627)
ββ{wtq}(22889)
ββ{wtq}(22997)
And here's what the process tabs shows me in System Monitor:
For completeness sake, here's what Mission Center says:
Thank you!
So:
- wtq 144MB
- wezterm-gui 331MB
- zsh 11MB
---------------------
- WTQ 486MB
Do you agree that the higher number of 486MB comes from the sum of wtq + all underlying processes, and that we seem to be at a stable ~150MB for wtq only? In other words, that wtq without GUI hovers around 150MB?
If so, we can further scope to wtqs memory usage, and consider the wild memory usage differences on process groups.
Secondly, if you do agree with the above, can you give me your thoughts on what you find acceptable for (a program like) wtq?
Of course, 150MB for a small thing in the background is kinda bulky, but given the probably effort I'm leaning towards considering ~150MB a reasonable target for now.
Honestly, after this digging, 150 mb is fine for a program written in something like C#; like it's wildly high for some other programming languages, but I can live with 150 mb.
Totally agree there, thanks! I'm looking for a proper goal for this particular issue, to scope things a bit.
That means for now, the goal is to keep the average usage around 150MB, which means separating the GUI in some way.
Later, we can look into more avenues, maybe AOT can help.
Thank you again for all your help, really appreciate it!