Repository navigation
os, dix, mi, render: optimize RAM consumption in background when idle - #3961
GermanAizek wants to merge 1 commit into
Conversation
ab524e9 to
2968091
Compare
| if [ "${{ github.repository }}" = "X11Libre/xserver" ] && [ "${{ github.event_name }}" != "pull_request" ]; then | ||
| docker push "$img:$tag" | ||
| if [ "${{ github.ref }}" = "refs/heads/master" ]; then | ||
| docker tag "$img:$tag" "$img:latest" | ||
| docker push "$img:latest" | ||
| fi | ||
| else | ||
| echo "Skipping docker push: write permissions to GHCR unavailable on pull requests or forks" | ||
| fi |
There was a problem hiding this comment.
looks unrelated to this PR - should be slit out to separate one.
There was a problem hiding this comment.
I accidentally pulled in local changes
2968091 to
81f1357
Compare
| void | ||
| dixTrimEvents(void) | ||
| { | ||
| if (swapEvent) { | ||
| free(swapEvent); | ||
| swapEvent = NULL; | ||
| swapEventLen = 0; | ||
| } | ||
| } | ||
|
|
There was a problem hiding this comment.
maybe we don't even need to keep that buffer global. it's not used often and could be allocated / freed when needed.
|
Merge Conflict found |
|
@GermanAizek has conflicts that need to be resolved. |
When the X server runs for extended periods or handles bursty client
workloads, significant memory bloat is retained across heap arenas,
unshrunk resource tables, event queues, client I/O buffers, and dormant
shared libraries even after all client resources are destroyed.
Implement comprehensive background idle memory reclamation without
changing memory allocators and preserving full ABI compatibility:
- Startup allocator tuning:
* Configure M_TRIM_THRESHOLD (128 KB) and M_ARENA_MAX (2).
* Configure M_MMAP_THRESHOLD (128 KB) to prevent runaway dynamic
threshold escalation that causes heap fragmentation.
- Idle background trim timer:
* Schedule an ABI-safe idle callback after 5 seconds of inactivity.
* Disarm the timer on incoming client traffic so active workloads
suffer zero overhead or latency penalty.
* Re-arm periodically (every 60 seconds) during sustained idle states,
and trigger trim on screensaver / DPMS power-saving events.
- Buffer and cache reclamation:
* Reclaim idle client input (oc->input) and output (oc->output) buffers,
along with AvailableInput and cached free buffer pools.
* Empty dix font pattern caches (patternCache and fontPatternCache).
* Downsize client resource bucket tables back to INITBUCKETS when
client resource counts shrink (preserving serverClient index 0).
* Compact mi input event queue (miEventQueue) back to initial size.
* Compact global glyph hash tables and clear deleted glyph tombstones.
- Clean non-core library page reclamation:
* Inspect /proc/self/maps on Linux and issue madvise(MADV_DONTNEED) on
purely clean file-backed segments (executable r-xp code and file-offset
zero rodata) of heavy dormant libraries (libLLVM, libz3, libstdc++,
libxml2, and Mesa DRI drivers).
* Strictly avoid writable or GNU_RELRO segments to preserve copy-on-write
dynamic relocations.
* Invoke malloc_trim(0) to release freed heap pages to the kernel.
- Robust listener socket binding:
* In _XSERVTransSocketUNIXCreateListener(), attempt direct bind() first
and only inspect/unlink stale files on EADDRINUSE to prevent race
conditions between concurrent servers under -displayfd.
- CI compatibility:
* Guard M_ARENA_MAX and HAVE_MALLOPT for Cygwin.
Signed-off-by: Herman Semenoff <GermanAizek@yandex.ru>
81f1357 to
1b5cf6a
Compare
Fix it 1b5cf6a |
eae2c21 to
483a172
Compare
|
@metux Haven’t you reviewed this PR yet? I specifically made all the other PRs drafts so that I could finish the work with the active ones first. |
|
@metux origin story malloc_trim() and algorithm In Unix systems, memory trimming is already available and complies with POSIX standards — it has been so since the end 90s. It’s just that many developers have forgotten about this technology. Back then, the price of RAM per 1 MB was high, just like it is now. That’s why they came up with the idea of manually freeing up memory earlier call signal to OS memallocator and using it for other processes without losing performance — but this requires manual work from programmer. |
| * Don't blindly unlink a pre-existing socket file: it may belong to a | ||
| * server that's still running (see unix_socket_is_live()). Only clean | ||
| * up and rebind if nobody answers there. | ||
| * Try to bind directly without unlinking first. If the socket file does |
There was a problem hiding this comment.
I think this should go to other commit, or even better other PR.
| #endif | ||
|
|
||
| static CARD32 | ||
| IdleTrimCallback(OsTimerPtr timer, CARD32 now, void *arg) |
There was a problem hiding this comment.
I'm afraid there are chance with timer callback like this to be source of unexplained latency spikes.
I don't know how it should be approached, one of suggestion to hook it on new opcode in xtest extension (the only few calls defined) and allow to be called manually
@metux, I’d like to raise a pressing issue about optimizing memory using malloc_trim by default (https://man7.org/linux/man-pages/man3/malloc_trim.3.html)
Regressions on x11perf not found.
The prices of RAM and flash memory continue to rise and are once again breaking records.
https://nl.pcpartpicker.com/trends/price/memory/#ram.ddr5.6000.2x16384
Solution for low RAM specs from Meta
In this regard, to optimize costs for purchasing RAM, Meta has decided to optimize compression instead of using ZRAM and ZSWAP.
I think we also need to value every user megabyte, because it’s unclear when prices for components will start to fall, and I hope you agree that x11libre also supports reuse electronic waste for ECO environmental purposes.
My benchmarks
Changes:
Implement background memory trimming and heap compaction when the X server
is idle, without changing the default glibc mem allocator or breaking ABI:
escalation that causes heap retention and fragmentation.
clients, along with AvailableInput and buffer pools (os/io.c).
and offset-0 rodata mappings of heavy non-core libraries (libLLVM,
libz3, libstdc++, libxml2, and Mesa DRI drivers).