Measure Recent Process Memory Activity with /proc/clear_refs
You will finish with a repeatable measurement of which pages a process touched during a chosen interval. The method reads /proc/PID/smaps, writes a selector to /proc/PID/clear_refs, waits, then reads Referenced: again. It measures recent activity, not the process's complete memory footprint.
The route
Jump straight to the step you need, or tick off Done means at the end.
Allow about ten minutes. You need a Linux shell and a process owned by your account. The examples use the local manpages package version 6.7-2, whose proc_pid_clear_refs(5) page is from Linux man-pages 6.7. This guide does not stop or restart a service, but clearing counters changes the observations made by other monitoring tools, so use a maintenance window for a production process.
1. Check that the interface exists
The file is available only when the kernel was built with CONFIG_PROC_PAGE_MONITOR. Check your own process first. These are ordinary, read-only commands:
$ uname -r
6.8.0-139-generic
$ ls -l /proc/self/clear_refs /proc/self/smaps
--w------- 1 user user 0 Sep 26 13:36 /proc/self/clear_refs
-r--r--r-- 1 user user 0 Sep 26 13:36 /proc/self/smaps
The dates and account names will differ. A missing clear_refs means this kernel does not expose the interface. Do not create a file under /proc; it is a kernel interface, not ordinary storage.
Checkpoint
Continue only if both paths exist. The target PID must still be alive when you inspect and clear it.
2. Choose a target and inspect its baseline
For a harmless first run, start a temporary process owned by you. It will not perform useful work, but it gives you a stable PID while you learn the sequence:
$ sleep 30 &
[1] 24831
$ PID=$!
$ test -r "/proc/$PID/smaps" && test -w "/proc/$PID/clear_refs" && echo "target is readable and writable"
target is readable and writable
Replace 24831 only in the displayed output if you copy a PID into a later command. In a script, keep the value in $PID. A process you do not own may be unreadable or unwritable even when it is visible in a process list. That is a permission boundary, not a reason to reach for sudo.
Record the current referenced total for the target. This adds the per-mapping values from smaps; it does not alter the process:
$ awk '/^Referenced:/ { total += $2 } END { print total " kB referenced" }' "/proc/$PID/smaps"
0 kB referenced
Your value may be non-zero and will vary with the program. The field is reported per mapping, so summing it gives a useful process-wide approximation.
3. Reset the referenced-page bits
Write 1 to reset the PG_Referenced and ACCESSED/YOUNG bits for all pages associated with the process:
$ printf '1\n' > "/proc/$PID/clear_refs"
$ echo "clear_refs write status: $?"
clear_refs write status: 0
This is the state-changing step. It does not free memory, compact memory, pause the process or make future accesses disappear. It changes the reference baseline used by later accounting. There is no undo command for the cleared bits; wait for new activity and take another measurement instead.
A successful write produces no normal output. A shell error such as "Permission denied" means the target is not writable by your account, or the process exited and its /proc directory vanished. Check the PID again before changing anything:
$ test -d "/proc/$PID" && echo "process is still running"
process is still running
4. Measure a defined interval
Choose the interval before starting it. Ten seconds is long enough for a small smoke test; a real workload may need a longer window. Keep the target running and do not treat the shell's own work as part of the target's workload:
$ INTERVAL=10
$ sleep "$INTERVAL"
$ awk '/^Referenced:/ { total += $2 } END { print total " kB referenced during the interval" }' "/proc/$PID/smaps"
0 kB referenced during the interval
A sleeping process can legitimately report zero or a small value. To measure useful activity, repeat the same procedure around the real workload: inspect, write 1, perform or observe the workload for a measured interval, then inspect again. Do not compare measurements made with different intervals or different workload phases.
For a compact before-and-after record, use a target that is already doing work and save the two totals outside /proc. The values are snapshots, not a durable log supplied by the kernel.
5. Select anonymous or file-mapped pages
Use 2 when you want to reset referenced and accessed bits only for anonymous pages. Use 3 for file-mapped pages. The rest of the workflow is unchanged:
$ printf '2\n' > "/proc/$PID/clear_refs" # anonymous pages
$ printf '3\n' > "/proc/$PID/clear_refs" # file-mapped pages
Run one selector at a time. Writing 3 does not mean "all pages plus file mappings"; it selects file-mapped pages. The manpage documents 1, 2 and 3 as separate behaviours. Values that are not listed have no effect, so do not invent combinations such as 6.
6. Know the other documented selectors
Selector 4, available since Linux 3.11, clears the soft-dirty bit for all pages. It is used with /proc/PID/pagemap by checkpoint and restore software to find pages dirtied after the reset. That is a different measurement from referenced-page activity and has different access and security considerations.
Selector 5, available since Linux 4.0, resets the process's peak resident set size to its current resident set size. It changes an accounting high-water mark, not the resident pages themselves. Avoid writing it to a service merely to make a monitoring graph look tidier; you lose the previous peak.
The feature is versioned by the kernel, not by the manpages package. The local manpage records selector 1 since Linux 2.6.22, selectors 2 and 3 since 2.6.32, selector 4 since 3.11 and selector 5 since 4.0. A newer or vendor-patched kernel can still differ, so check the running kernel's interface and permissions before automating it.
7. Clean up the test process
End the temporary process after the test. This is the only process lifecycle change in the example:
$ kill "$PID"
$ wait "$PID" 2>/dev/null || true
$ test ! -e "/proc/$PID" && echo "temporary process is gone"
temporary process is gone
If you used an existing service instead, do not kill it as a cleanup step. Leave the service running and record that its reference baseline was reset. The practical recovery is simply to wait for a new observation interval; the previous reference state cannot be restored.
Done means
/proc/PID/clear_refsand/proc/PID/smapsexist for the target.- You confirmed the target is alive and writable by your account.
- You read
Referenced:before and after a named interval. - You used selector
1,2or3for the page class you intended. - You treated the result as approximate activity, not total memory usage.
- You did not overwrite a service's peak accounting or stop a production process by accident.