Skip to content

XceptN’s Tech Stuff

All About Tech

Analyzing Memory Usage on Linux 6.19

Posted on April 2, 2026April 3, 2026 By XceptN No Comments on Analyzing Memory Usage on Linux 6.19

Analyzing Memory Usage on Linux 6.19

I have been looking forward to running Linux 6.19 on my main workstation for some time now. Arch shipped it in their April ISO and I upgraded almost immediately. One thing I always do after a major kernel update is stare at /proc/meminfo for a while. Not because something is broken. Just because the file keeps growing, and I wanted to understand what every single line actually means on a modern kernel.

I suspect most of us glance at free -m and move on. That is perfectly fine for daily use. Still, if you really want to understand where your RAM goes — and more importantly, where the kernel THINKS it goes — you need to read /proc/meminfo directly. So let me walk you through it, section by section.

The Basics: What You Already Know

I rely on a mental model that groups the output into layers. The first layer is the stuff everyone recognises:

MemTotal:       32858820 kB
MemFree:        21001236 kB
MemAvailable:   27214312 kB
Buffers:          581092 kB
Cached:          5587612 kB
SwapCached:            0 kB

MemTotal is your physical RAM minus what the kernel reserved at boot for its own binary and some firmware tables. It does NOT change at runtime. MemFree is the truly unused memory — pages that nobody has claimed. On a healthy system this number can be quite low and that is perfectly normal. Linux prefers to use RAM for caching rather than leave it empty.

MemAvailable appeared in kernel 3.14 and I think it is the single most important field in the whole file. It estimates how much memory is available for new applications without swapping. The kernel calculates it from MemFree plus reclaimable caches, minus watermarks. The formula is a bit involved — it accounts for zone watermarks, file-backed pages, and reclaimable slab. I have seen people confuse MemFree with MemAvailable for years. They are VERY different things.

Buffers is memory used for raw disk block metadata. Cached is the page cache — file contents the kernel keeps in RAM so it does not have to re-read from disk. SwapCached is the interesting one: pages that exist both in RAM and in the swap file simultaneously. If the system needs to swap them out again, it can skip the write because the copy on disk is already up to date. Quite clever.

Active vs Inactive Pages

Active:          3237152 kB
Inactive:        7586256 kB
Active(anon):      94064 kB
Inactive(anon):  4570616 kB
Active(file):    3143088 kB
Inactive(file):  3015640 kB
Unevictable:           0 kB
Mlocked:               0 kB

I preferred to think of this as the kernel’s LRU bookkeeping. Pages move between Active and Inactive lists based on how recently they were accessed. The kernel splits them further into anonymous pages (heap, stack, anything not backed by a file) and file-backed pages (the page cache, basically).

Active(anon) being small usually means your applications are not actively touching a lot of heap memory right now. Inactive(anon) being large could mean the system swapped things around recently, or that Transparent Huge Pages inflated the anonymous count.

Unevictable and Mlocked track pages that cannot be reclaimed — typically because a process called mlock() on them. Databases like PostgreSQL and crypto applications do this. If Mlocked is unexpectedly large on your server, that is when I start investigating.

Swap and Zswap: The Modern Duo

SwapTotal:             0 kB
SwapFree:              0 kB
Zswap:              1904 kB
Zswapped:           7792 kB

I run my workstation without traditional swap because I have 32 GB of RAM and I am a bit stubborn about it. Still, Zswap and Zswapped are relatively new fields and worth understanding.

Zswap is the compressed pool size in RAM. Zswapped is the original uncompressed size of pages stored there. So in the example above, 7792 kB of page data was compressed into 1904 kB — roughly a 4:1 ratio. That is when I realised how effective zswap can be for certain workloads. The kernel compresses pages before they hit the actual swap device, which means less I/O and faster recovery.

These two fields showed up around kernel 6.2 and they are incredibly useful for diagnosing memory pressure on systems that use zswap. If Zswapped keeps growing but SwapFree stays high, zswap is doing its job. If Zswapped is huge AND SwapFree is dropping, you are in real trouble.

Dirty Pages and Writeback

Dirty:                12 kB
Writeback:             0 kB

Dirty is file-backed memory that has been modified but not yet written to disk. Writeback is memory currently being written out. On a healthy system these numbers should be quite low most of the time. If Dirty climbs into the hundreds of megabytes and stays there, your storage might be slow or the dirty_ratio tunables need adjustment.

I have seen Writeback spike to several gigabytes on NFS mounts with congested networks. Unfortunately, the only real fix was faster storage or tuning dirty_writeback_centisecs.

Anonymous and Mapped Pages

AnonPages:       4654780 kB
Mapped:           266244 kB
Shmem:              9976 kB

AnonPages is the total memory used by anonymous mappings — your application heaps, stacks, and anything mmap’d with MAP_ANONYMOUS. This is the real “application memory” number, more or less.

Mapped is memory mapped into user-space page tables from file-backed sources. Shared libraries, memory-mapped files, that sort of thing. Shmem covers shared memory segments, tmpfs, and SysV IPC. If you run a lot of containers with tmpfs mounts, Shmem can get surprisingly large.

Kernel Memory: Slab and Friends

KReclaimable:     517708 kB
Slab:             660044 kB
SReclaimable:     517708 kB
SUnreclaim:       142336 kB
KernelStack:       11168 kB

This section is where things get really interesting for debugging. Slab is the total memory used by the kernel’s slab allocator for internal data structures — dentries, inodes, network buffers, all sorts of things. It splits into SReclaimable (caches the kernel can drop under pressure) and SUnreclaim (structures that must stay).

As far as I can remember, KReclaimable was added in kernel 4.20 and it is a superset of SReclaimable. It includes other reclaimable kernel allocations beyond just slab caches.

KernelStack is the memory for kernel thread stacks. Each thread in the system needs one. On a server running thousands of threads, this adds up. I have seen it reach 50-60 MB on busy Java application servers. Not huge, but not nothing either.

Page Tables: The New and the Old

PageTables:        20540 kB
SecPageTables:         0 kB

PageTables is the memory consumed by the page table hierarchy that maps virtual addresses to physical ones. Every process needs page tables, and processes with large virtual address spaces consume more.

SecPageTables is a relatively recent addition. It tracks secondary page tables — currently this means KVM MMU allocations on x86 and arm64. If you run virtual machines, this is where you see the memory cost of nested paging. On a bare-metal workstation it will sit at zero. On a Proxmox host with a dozen VMs, it may climb to a few megabytes.

The Commit Story

CommitLimit:    16429408 kB
Committed_AS:    7715148 kB

CommitLimit is the total amount of memory the system allows to be committed. It only matters if vm.overcommit_memory is set to 2 (strict mode). The formula is roughly (SwapTotal + MemTotal * overcommit_ratio / 100).

Committed_AS is how much memory has been allocated by processes in total. This includes malloc()‘d but untouched memory. A process that allocates 1 GB but only writes to 300 MB still shows as 1 GB here. If Committed_AS exceeds CommitLimit and you are in strict mode, new allocations will fail. In the default overcommit mode (mode 0), the kernel uses heuristics and these numbers are more informational than restrictive.

Vmalloc, Percpu, and Hardware

VmallocTotal:  34359738367 kB
VmallocUsed:        40444 kB
VmallocChunk:           0 kB
Percpu:             29312 kB
EarlyMemtestBad:        0 kB
HardwareCorrupted:      0 kB

VmallocTotal is the total vmalloc address space — on 64-bit systems this number is enormous and basically meaningless. VmallocUsed and VmallocChunk have been hardcoded to 0 since kernel 4.4 on most architectures. Still, on some configurations you might see actual values in VmallocUsed. Sort of a legacy leftover in the output.

Percpu tracks memory allocated through the per-CPU allocator. The kernel creates per-CPU copies of certain data structures for performance — avoiding cache bouncing between cores. On systems with many CPUs and lots of cgroups, this can grow significantly. You might see 60+ MB on 64-core servers running container workloads.

EarlyMemtestBad appears if you boot with memtest in the kernel command line. It shows how much RAM the early memory test flagged as bad. HardwareCorrupted is similar but tracks pages the kernel itself marked as corrupted at runtime, typically through MCE (Machine Check Exception) handling. If this is non-zero, you have a hardware problem. Replace your DIMMs.

Huge Pages: Three Flavours

AnonHugePages:   4149248 kB
ShmemHugePages:        0 kB
ShmemPmdMapped:        0 kB
FileHugePages:         0 kB
FilePmdMapped:         0 kB
HugePages_Total:       0
HugePages_Free:        0
HugePages_Rsvd:        0
HugePages_Surp:        0
Hugepagesize:       2048 kB
Hugetlb:               0 kB

There are really three different huge page systems in modern Linux and the meminfo file mixes them all together.

AnonHugePages comes from Transparent Huge Pages (THP). The kernel automatically promotes regular 4 kB anonymous pages to 2 MB pages when it can. This number can be very large on systems with THP enabled, which is the default on most distributions. I noticed my workstation showed over 4 GB of THP-backed anonymous memory, which is a good sign — means the kernel found enough contiguous physical memory to use large pages. Note that for some database systems, it could be required or preferred to have THP disabled.

ShmemHugePages and ShmemPmdMapped are the THP equivalent for shared memory and tmpfs. FileHugePages and FilePmdMapped cover THP for file-backed mappings — a feature that has been gradually expanding across kernel versions.

The HugePages_* fields are for the older, statically allocated hugetlbfs system. You pre-allocate a pool via sysctl or boot parameters, and applications like databases or DPDK explicitly request them. On my workstation all zeros because I do not use hugetlbfs. On a production database server you would typically see these configured.

CMA and Unaccepted Memory

CmaTotal:              0 kB
CmaFree:               0 kB
Unaccepted:            0 kB

CmaTotal and CmaFree track the Contiguous Memory Allocator region. This matters on embedded systems and devices that need large physically contiguous memory blocks — think DMA for camera hardware, GPU buffers on ARM SoCs, that kind of thing. On a desktop x86 system, usually zero.

Unaccepted is quite new and appeared to support confidential computing features like Intel TDX and AMD SEV-SNP. In those environments, memory offered by the hypervisor must be explicitly “accepted” by the guest kernel before use. Unaccepted shows how much offered memory the guest has not yet accepted. On a regular bare-metal system, zero. On a confidential VM, this can be temporarily non-zero during boot or memory hot-add. Make note that this does not mean “rejected/refused”. It is just “not yet accepted”.

DirectMap: The Kernel’s Linear Mapping

DirectMap4k:      245760 kB
DirectMap2M:     8142848 kB
DirectMap1G:    26214400 kB

These lines show how the kernel maps physical RAM into its own linear address space. The kernel prefers the largest page size possible for efficiency — 1 GB pages reduce TLB pressure significantly. If DirectMap4k keeps growing over time, something is fragmenting the kernel’s direct mapping. This can happen when CONFIG_DEBUG_PAGEALLOC is active or when certain device drivers request uncached mappings.

On a healthy 32 GB system, most memory should appear under DirectMap1G and DirectMap2M. The DirectMap4k portion should be small — a few hundred megabytes at most.

Putting It All Together: A Quick Sanity Check

I wrote a small mental checklist I run through whenever I read /proc/meminfo on a system:

  1. Is MemAvailable much larger than MemFree? Good — means the page cache is doing its job and the kernel can reclaim it.
  2. Is Committed_AS way above MemTotal + SwapTotal? You are overcommitting heavily. Might be fine, might not be.
  3. Is SUnreclaim growing over time? Could be a kernel memory leak. Check slabtop for details.
  4. Is Dirty persistently high? Storage bottleneck.
  5. Are Zswap and Zswapped climbing? Memory pressure is building, but zswap is handling it.
  6. Is HardwareCorrupted non-zero? Fix your hardware.
  7. Is SecPageTables unexpectedly large? You might be running too many VMs or your nested paging is inefficient.

One More Thing: kB Does Not Mean kB

I almost forgot this one and it is a bit embarrassing. The /proc/meminfo file labels everything as “kB” but the values are actually in kibibytes (KiB, 1024 bytes), not kilobytes (1000 bytes). The kernel developers know about this inconsistency but they cannot change it without breaking every monitoring tool on the planet. So “kB” in meminfo means 1024 bytes. Always has, probably always will.

Wrapping Up

I have been reading /proc/meminfo on Linux for over two decades and it still teaches me something new with every major kernel release. The 6.19 output has close to 50 fields on a typical x86_64 system. Most of them are boring most of the time — and that is exactly how it should be. The interesting part is knowing which ones to look at when things go wrong.

If you want to dig deeper, the kernel documentation at Documentation/filesystems/proc.rst in the source tree is the canonical reference. The man page proc_meminfo(5) is also quite decent on recent distributions.

Hope that helps… Take care…

kernel, linux, virtualization Tags:analysis, linux, memory, memory management

Post navigation

Previous Post: Enabling “real-time-protection” with ClamAV on Ubuntu 24.04 Desktop for Palo Alto Networks Global Protect (PanGP) VPN

Related Posts

USB TV BOX desktop
Open Source Virtualization for Smaller Carbon Footprint linux
backup the mbr linux
How to Recursively “grep” a Subdirectory for a List of Files desktop
Building Binaries from Sources development
Importance of Price, Quality and Support Effectiveness for Virtualization linux

Leave a Reply Cancel reply

Your email address will not be published. Required fields are marked *

Recent Posts

  • Analyzing Memory Usage on Linux 6.19
  • Enabling “real-time-protection” with ClamAV on Ubuntu 24.04 Desktop for Palo Alto Networks Global Protect (PanGP) VPN
  • Dipping Toes into Nix Package Manager | Installing Freeplane
  • Fujitsu Workplace Protect Face Recognition Best Practices on Q704
  • Fujitsu STYLISTIC Q704 Fingerprint Scanner Problems

Recent Comments

  1. r0cky on Fujitsu LIFEBOOK UH572 Ultrabook Touch Pad Review: Linux
  2. XceptN on Fujitsu LIFEBOOK UH572 Ultrabook Touch Pad Review: Linux
  3. r0cky on Fujitsu LIFEBOOK UH572 Ultrabook Touch Pad Review: Linux
  4. Kaylee on Mounting an LVM Logical Volume in an Oracle VM Disk Image
  5. Theron Conrey on Open Source Virtualization for Smaller Carbon Footprint

Archives

  • April 2026
  • September 2025
  • June 2024
  • November 2014
  • October 2014
  • April 2014
  • March 2014
  • December 2012
  • November 2012
  • October 2010
  • April 2010
  • April 2009
  • March 2009
  • February 2009
  • January 2009
  • December 2008
  • November 2008
  • October 2008
  • September 2008

Categories

  • blogging
  • communication
  • desktop
  • development
  • firmware
  • Fujitsu
  • gprs
  • gps
  • hardware
  • internet
  • java
  • kernel
  • keyboard
  • linux
  • masteryourbiz
  • mms
  • mobile
  • multimedia
  • network
  • OracleVM
  • palm
  • python
  • rokr e6
  • social media networking
  • storage
  • sysadm
  • tablet
  • twitter
  • virtualization
  • wap
  • windows
  • wordpress
  • xen

Copyright © 2026 XceptN’s Tech Stuff.

Powered by PressBook Masonry Dark