Skip to content

PMM-15398 Count shared memory as used, not cache - #5855

Open
theTibi wants to merge 1 commit into
mainfrom
PMM-15398-memory-used-shmem
Open

PMM-15398 Count shared memory as used, not cache#5855
theTibi wants to merge 1 commit into
mainfrom
PMM-15398-memory-used-shmem

Conversation

@theTibi

@theTibi theTibi commented Aug 28, 2026

Copy link
Copy Markdown
Contributor

Ticket number: PMM-15398

Feature build: Percona-Lab/pmm-submodules#4550

Summary

  • Bug: PMM's node Used memory never counts PostgreSQL shared_buffers. The reporter varied shared_buffers from 128 MB to 8 GB on PostgreSQL 18.6 and PMM never showed more than ~2 GB used, while free showed ~10 GB.
  • Root cause: Used = MemTotal - (MemFree + Buffers + Cached). /proc/meminfo:Cached includes Shmem, and shared_buffers is anonymous shared memory — so it was subtracted out of Used and re-plotted as Cache. MySQL looked correct only because it allocates AnonPages.
  • Fix: Used now subtracts (Cached + SReclaimable - Shmem) instead of Cached, and the Cache series plots that same quantity. Folding in SReclaimable also addresses PMM-11119.
- Used  = MemTotal - MemFree - Buffers - Cached
+ Used  = MemTotal - MemFree - Buffers - (Cached + SReclaimable - Shmem)
+ Cache = Cached + SReclaimable - Shmem

Panels changed

File Panel Series
OS/Node_Summary.json Memory Utilization Used, Cache
OS/Memory_Details.json Memory Usage Used, Cached
OS/Nodes_Compare.json $node_name - Memory Usage Used, Cached
OS/Nodes_Overview.json Top 5 Used Memory both targets
managed/services/telemetry/config.default.yml PMMNodeMemoryUsage

The telemetry entry carries a character-for-character clone of the Node_Summary expression; without it the shipped pmm_server_node_memory_usage series would permanently disagree with the dashboard it was copied from.

RDS is deliberately unaffected

percona/rds_exporter exports node_memory_{MemTotal,MemFree,Buffers,Cached}_bytes but not SReclaimable, Shmem or MemAvailable. A plain rewrite would make these panels return an empty series for every RDS node. The new terms therefore carry a zero-fallback:

Cached + (SReclaimable - Shmem or Cached * 0)

or binds loosest, so this is (SReclaimable - Shmem) or (Cached * 0). Verified by fault injection against a live VictoriaMetrics: with those metrics absent the output is bit-identical to the previous expression. Note this relies on MetricsQL ignoring __name__ in set-operator matching (Prometheus does not) — the same property PMM's existing MemAvailable or (…) idiom already depends on.

Verification

Live PMM Server 3.9.0, real PostgreSQL 18.6 with shared_buffers=1GB prewarmed via pg_prewarm, 905 MB pgbench dataset, node pmm15398-pg-node. Before/after captured over the identical 23-minute window by swapping only the dashboard JSON.

Series Before After
Used 5.52 GiB 6.11 GiB
Cache 1.71 GiB 1.12 GiB
Free 319.51 MiB 319.51 MiB
Buffers 113.84 MiB 113.84 MiB
Total 7.65 GiB 7.65 GiB

/proc/meminfo at that moment: Shmem = 1,044,932 kB (the shared_buffers), SReclaimable = 374,984 kB. free -m reported 6393 MB used.

  • Stacked panel still sums to MemTotal exactly — residual 0.000 MiB.
  • Error against free drops from -14.2% to -3.1%.
  • Rendered legend cross-checked against a direct VictoriaMetrics query (no browser): Used 6.11 = 6.11, Total 7.65 = 7.65.

Please read before approving

  • This is not parity with free(1). Modern free computes MemTotal - MemAvailable, a third definition again. This change closes most of the gap but a ~3% residual remains, caused by MemAvailable's watermark and half-slab discount. Home_Dashboard → "Top 20 Used Memory" already uses the MemAvailable definition, so it will sit ~200 MB above "Top 5 Used Memory" on the same node. Before this change that gap was ~870 MB.
  • The Used line steps upward on every existing installation. Alert rules and customer baselines keyed to the old expression will shift. This needs a release note.
  • A stacked-panel alternative that matches free exactly is not available, because MemTotal - MemAvailable breaks the Used + Free + Buffers + Cache = MemTotal identity the stacked panels depend on.

Test plan

  • python3 dashboards/misc/cleanup-dash.py --check-only <file> — clean on all 4 dashboards
  • plugin.json referenced-path check and JSON validity
  • go test ./managed/services/telemetry/ -run TestServiceConfigUnmarshal — PASS (TestRunTelemetryService fails identically on main; it needs a testdb Postgres)
  • Live before/after on PostgreSQL 18 with shared_buffers=1GB, identical time window
  • RDS degradation path fault-injected — output bit-identical to current main
  • Independent review, two rounds — 0 high, 0 medium
  • Screenshots attached to PMM-15398
  • pmm-submodules (FB) PR: PMM-15398 Build dashboards memory fix Percona-Lab/pmm-submodules#4550

Related

  • Closes the SReclaimable half of PMM-11119 (Take into account slab cache in Memory Utilization)
  • Relates to PMM-12870 (RDS memory charts miscalculating free memory)
  • Not fixed here: Memory_Details.json has a pre-existing av_over_time typo (missing g) in the hidden "Used Swap" target of the same panel. Dormant because the target is hide: true; present on main.

Used was MemTotal - (MemFree + Buffers + Cached). /proc/meminfo:Cached
includes Shmem, and PostgreSQL shared_buffers is anonymous shared
memory, so every byte of it was subtracted out of Used and re-drawn as
Cache. A node with shared_buffers=8G reported ~1.5G used while free(1)
reported ~10G. MySQL was unaffected because it allocates AnonPages.

Used now subtracts (Cached + SReclaimable - Shmem) instead of Cached,
and the Cache series plots that same quantity, so the stacked panels
still sum to MemTotal exactly. Folding in SReclaimable also addresses
PMM-11119.

rds_exporter exports MemTotal, MemFree, Buffers and Cached but not
SReclaimable or Shmem, so the new terms carry a zero-fallback:

    Cached + (SReclaimable - Shmem or Cached * 0)

With those metrics absent the result is bit-identical to the previous
expression, leaving RDS nodes unchanged.

The same expression is cloned in the telemetry config; it is updated
here so the shipped pmm_server_node_memory_usage series does not
diverge from the dashboard it was copied from.

This is not parity with free(1), which uses MemTotal - MemAvailable.
Measured on a PostgreSQL 18 node with shared_buffers=1G, the error
against free drops from -14.2% to -3.1%. The Used line steps upward on
existing installations, so alert rules keyed to the old expression will
shift.

Signed-off-by: theTibi <tkorocz@gmail.com>
@codecov

codecov Bot commented Aug 28, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 43.80%. Comparing base (31318c7) to head (b516780).
⚠️ Report is 156 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff             @@
##             main    #5855      +/-   ##
==========================================
+ Coverage   43.59%   43.80%   +0.21%     
==========================================
  Files         415      432      +17     
  Lines       43134    35298    -7836     
  Branches        0      591     +591     
==========================================
- Hits        18804    15463    -3341     
+ Misses      22454    18311    -4143     
+ Partials     1876     1524     -352     

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@theTibi
theTibi marked this pull request as ready for review August 29, 2026 18:46
@theTibi
theTibi requested review from a team and Nailya as code owners August 29, 2026 18:46
@theTibi
theTibi requested review from 4nte, ademidoff, fabio-silva and matejkubinec and removed request for a team August 29, 2026 18:46
@coderabbitai

coderabbitai Bot commented Aug 29, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 42e349cd-7dbb-4c3c-bab6-0ce3a8ef3a11

📥 Commits

Reviewing files that changed from the base of the PR and between a5e6608 and b516780.

📒 Files selected for processing (5)
  • dashboards/dashboards/OS/Memory_Details.json
  • dashboards/dashboards/OS/Node_Summary.json
  • dashboards/dashboards/OS/Nodes_Compare.json
  • dashboards/dashboards/OS/Nodes_Overview.json
  • managed/services/telemetry/config.default.yml
🔗 Linked repositories identified

CodeRabbit considers these linked repositories for cross-repo context during reviews:

  • percona/pmm-qa (manual)
  • percona/pmm (manual)

Included review availability: Your plan provides up to 4 included reviews per hour; 3 remain after this review.


Walkthrough

The change updates memory calculations in four OS dashboards and the PMMNodeMemoryUsage telemetry query. Used-memory expressions now subtract SReclaimable - Shmem in addition to free, buffer, and cached memory. Cached-memory expressions now add the same reclaimable-minus-shared value. PromQL fallbacks use cached memory multiplied by zero when the reclaimable or shared metrics are unavailable.

Merge Risk: ⚪ Minimal · up to b5167

The change updates memory accounting expressions and their matching telemetry definition across the affected dashboards. No actionable merge-blocking risk remains beyond normal checks and review.

🚥 Pre-merge checks | ✅ 4
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly identifies the main change: counting shared memory as used rather than cache. It also includes the relevant ticket number.
Description check ✅ Passed The description is complete and directly related to the changes. It includes the ticket, feature build, root cause, implementation details, affected panels, compatibility behavior, verification result…
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Full details: Description check

Explanation

The description is complete and directly related to the changes. It includes the ticket, feature build, root cause, implementation details, affected panels, compatibility behavior, verification results, risks, and related work.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

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.

2 participants