Skip to content

Memory regression tests - #275

Open
alan-george-lk wants to merge 13 commits into
mainfrom
alan/feature-memory-regression-tests
Open

alan-george-lk wants to merge 13 commits into
mainfrom
alan/feature-memory-regression-tests

Conversation

@alan-george-lk

@alan-george-lk alan-george-lk commented Oct 8, 2026 •

Copy link
Copy Markdown
Collaborator

This PR introduces a new test binary called memory_tester for Linux, which has the following features:

  • Configurable common scenarios
    • Examples: publishing tracks, room joining/closure
  • RSS and thread usage tracking
  • Configurable repeated iterations, acceptable memory and thread growth bounds

CI is also updated to run this tester and provide a nice markdown table report of the results, and fail jobs that introduce changes that fail this.

Documentation is also updated around testing in general, as it was a bit out of date.

Results

Here are two FFI release results with the following params:

Iterations: 100
Warmup: 20
Threshold: RSS growth ≤ 8 MiB; thread growth ≤ 0.

Prior release livekit-ffi/v0.12.81 results:

Scenario RSS 0→20 RSS 20→100 Threads 0→20 Threads 20→100 Status
audio-track +60.63 MiB -2.64 MiB +28 0 ✅ PASS
video-track +61.43 MiB -2.62 MiB +28 0 ✅ PASS
data-track +53.88 MiB +0.03 MiB +2 0 ✅ PASS
room-reuse +53.54 MiB +3.47 MiB +2 0 ✅ PASS
room-client-leave +53.66 MiB +0.12 MiB +2 0 ✅ PASS
room-server-delete +143.46 MiB +108.94 MiB +105 +400 ❌ FAIL

Current FFI release results:

Scenario RSS 0→20 RSS 20→100 Threads 0→20 Threads 20→100 Status
audio-track +17.36 MiB +0.19 MiB +12 0 ✅ PASS
video-track +16.74 MiB -0.05 MiB +7 0 ✅ PASS
data-track +12.30 MiB +0.03 MiB +1 0 ✅ PASS
room-reuse +12.09 MiB 0.00 MiB +1 0 ✅ PASS
room-client-leave +12.10 MiB +0.05 MiB +1 0 ✅ PASS
room-server-delete +12.11 MiB +0.08 MiB +1 0 ✅ PASS

@alan-george-lk
alan-george-lk force-pushed the alan/feature-memory-regression-tests branch from 2a21a8a to d638cca Compare October 15, 2026 03:06
@alan-george-lk
alan-george-lk marked this pull request as ready for review October 15, 2026 23:35
@alan-george-lk
alan-george-lk requested review from a team and xianshijing-lk as code owners October 15, 2026 23:35
@alan-george-lk alan-george-lk changed the title WIP: Memory regression tests Memory regression tests Oct 15, 2026

@devin-ai-integration devin-ai-integration Bot left a comment •

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note

Newer findings are available below. Devin Review posted a newer report on this PR, in addition to the findings presented here.

🔍 Devin Review: 2 flags

Not posted on this PR by your GitHub settings — view them in Devin Review. (Configure)

Devin Review

@devin-ai-integration devin-ai-integration Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Devin Review found 2 new potential issues.

2 flags not posted on this PR by your GitHub settings — view them in Devin Review. (Configure)

Devin Review

Comment on lines +605 to +607
if (current.process.threads > warmup.process.threads) {
first_thread_growth_iteration = iteration;
first_thread_growth = std::move(current);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Transient thread obscures leak start

When a transient worker raises the count after warmup, first_thread_growth_iteration latches that cycle. If the worker exits before a later leak, the final diagnostic reports the transient cycle as the growth onset.

Learn more

The diagnostic records the first cycle whose thread count exceeds the quiescent warmup count. This is a one-time latch: the final report never checks whether the extra thread survived. A temporary teardown worker can therefore take the place of the first persistent increase in a run that eventually fails the thread gate.

Example: Warmup has three threads. Cycle 21 briefly has four, cycle 22 returns to three, and a leaked worker first appears at cycle 90. The final count is four, but the diagnostic says growth first appeared after cycle 21.

Recommended fix: Track transitions back to the warmup count and record the start of the current sustained growth interval, or label the recorded iteration explicitly as the first transient count increase rather than the leak onset.

Devin Review


Was this helpful? React with 👍 or 👎 to provide feedback.

Comment on lines +276 to +279
if (next.process.threads != snapshot.process.threads) {
stable_since = std::chrono::steady_clock::now();
} else if (std::chrono::steady_clock::now() - stable_since >= kThreadQuiescencePeriod) {
return next;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Thread churn passes quiescence check

When one worker exits as another starts, sampleQuiescentProcess sees an unchanged thread count and declares quiescence. A checkpoint can include active teardown workers, giving the leak gate a false baseline or final count.

Learn more

Checkpoint sampling waits for a stable number of threads, but equal totals do not mean that the same threads remained alive. The cycle loop runs connection and track teardown repeatedly, so short-lived workers are precisely what this check is meant to exclude. Workers that are replaced between polls leave the total unchanged and allow a checkpoint while teardown is still running.

Example: A checkpoint starts with three threads. On successive polls one teardown worker exits while another starts; every poll still sees three. After 500 ms the function accepts the snapshot even though none of the sampled workers has survived the entire period.

Recommended fix: Track the set of thread IDs from /proc/self/task across polls and reset the stable interval when membership changes; keep thread names only for reporting.

Devin Review


Was this helpful? React with 👍 or 👎 to provide feedback.

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