Skip to content

Performance Improvements - #61

Open
Ipiano wants to merge 2 commits into
KDE:masterfrom
Ipiano:ads/perf-improvements
Open

Performance Improvements#61
Ipiano wants to merge 2 commits into
KDE:masterfrom
Ipiano:ads/perf-improvements

Conversation

@Ipiano

@Ipiano Ipiano commented Jul 14, 2026

Copy link
Copy Markdown

Background - I run heaptrack on an embedded linux device that has a similar amount of horsepower to later Raspberry Pis. The application I'm working on is a Qt-QML application with custom 3d rendering and some pretty heavy data processing - you might imagine there's quite a bit of heap allocation going on. After making these changes, I'm able to run the project without the whole thing grinding to an unusable halt.

Two changes here, one per commit

  • Change the mutex lock wait strategy
    • Using the futex wait-for functionality instead of a try-lock, wait loop improves performance in heavily concurrent applications. PThreads is able to do a better job waking up threads quickly when we let it handle the try-then-wake loop like this; and the strategy that the kernel uses to schedule short sleeps can actually cause a "sleep 1 microsecond" to end up being closer to 50 us due to the timer coelescing behaviors, depending on your kernel settings and process priority.
  • Add an option to limit stack depth
    • Running perf to record a trace of my process while it's being heaptracked shows that the stack unwind is the most expensive part of the heaptrack overhead. I don't need a full 64 frames of the stack to figure out what's going on in most cases, and cutting it down to 32 or 16 improves performance massively.

Andrew Stelter added 2 commits July 14, 2026 10:37
The contended-lock path spun on try_lock with 1us sleeps in between.
The kernel's default timer slack (50us) inflates each of those sleeps
to ~50us, so under multi-threaded allocation pressure every contended
malloc/free stalled far longer than the critical section it waited for.

Use a timed_mutex and wait on it directly; the 1ms timeout only bounds
how long a pending shutdown request can go unnoticed, preserving the
deadlock-avoidance behavior of the old loop.
Unwinding the stack on every allocation is the dominant per-thread cost
of tracking, and it scales linearly with stack depth. Allow capping the
captured depth below the fixed MAX_SIZE of 64 via the
HEAPTRACK_UNWIND_DEPTH environment variable, exposed through the new
--unwind-depth option of the heaptrack script. The default stays 64.

Invalid values are rejected with a warning rather than clamped, so a
typo cannot silently produce single-frame traces.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant