Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adding 'slab' info to virtual_memory #1239

Merged
merged 1 commit into from
Mar 17, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion docs/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -266,6 +266,7 @@ Memory
- **active** *(UNIX)*: memory currently in use or very recently used, and so
it is in RAM.
- **inactive** *(UNIX)*: memory that is marked as not used.
- **slab** *(Linux)*: in-kernel data structures cache.
- **buffers** *(Linux, BSD)*: cache for things like file system metadata.
- **cached** *(Linux, BSD)*: cache for various things.
- **shared** *(Linux, BSD)*: memory that may be simultaneously accessed by
Expand All @@ -284,7 +285,7 @@ Memory
>>> import psutil
>>> mem = psutil.virtual_memory()
>>> mem
svmem(total=10367352832, available=6472179712, percent=37.6, used=8186245120, free=2181107712, active=4748992512, inactive=2758115328, buffers=790724608, cached=3500347392, shared=787554304)
svmem(total=10367352832, available=6472179712, percent=37.6, used=8186245120, free=2181107712, active=4748992512, inactive=2758115328, buffers=790724608, cached=3500347392, shared=787554304, slab=199348224)
>>>
>>> THRESHOLD = 100 * 1024 * 1024 # 100MB
>>> if mem.available <= THRESHOLD:
Expand Down
9 changes: 7 additions & 2 deletions psutil/_pslinux.py
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,7 @@ class IOPriority(enum.IntEnum):
# psutil.virtual_memory()
svmem = namedtuple(
'svmem', ['total', 'available', 'percent', 'used', 'free',
'active', 'inactive', 'buffers', 'cached', 'shared'])
'active', 'inactive', 'buffers', 'cached', 'shared', 'slab'])
# psutil.disk_io_counters()
sdiskio = namedtuple(
'sdiskio', ['read_count', 'write_count',
Expand Down Expand Up @@ -441,6 +441,11 @@ def virtual_memory():
inactive = 0
missing_fields.append('inactive')

try:
slab = mems[b"Slab:"]
except KeyError:
slab = 0

used = total - free - cached - buffers
if used < 0:
# May be symptomatic of running within a LCX container where such
Expand Down Expand Up @@ -481,7 +486,7 @@ def virtual_memory():
warnings.warn(msg, RuntimeWarning)

return svmem(total, avail, percent, used, free,
active, inactive, buffers, cached, shared)
active, inactive, buffers, cached, shared, slab)


def swap_memory():
Expand Down
26 changes: 26 additions & 0 deletions psutil/tests/test_linux.py
Original file line number Diff line number Diff line change
Expand Up @@ -237,6 +237,31 @@ def test_available(self):
free_value, psutil_value, delta=MEMORY_TOLERANCE,
msg='%s %s \n%s' % (free_value, psutil_value, out))

def test_slab(self):
# Emulate /proc/meminfo because neither vmstat nor free return slab.
def open_mock(name, *args, **kwargs):
if name == '/proc/meminfo':
return io.BytesIO(textwrap.dedent("""\
Active(anon): 6145416 kB
Active(file): 2950064 kB
Inactive(anon): 574764 kB
Inactive(file): 1567648 kB
MemAvailable: -1 kB
MemFree: 2057400 kB
MemTotal: 16325648 kB
SReclaimable: 346648 kB
Slab: 186836 kB
""").encode())
else:
return orig_open(name, *args, **kwargs)

orig_open = open
patch_point = 'builtins.open' if PY3 else '__builtin__.open'
with mock.patch(patch_point, create=True, side_effect=open_mock) as m:
ret = psutil.virtual_memory()
assert m.called
self.assertEqual(ret.slab, 191320064)

def test_warnings_on_misses(self):
# Emulate a case where /proc/meminfo provides few info.
# psutil is supposed to set the missing fields to 0 and
Expand Down Expand Up @@ -280,6 +305,7 @@ def open_mock(name, *args, **kwargs):
self.assertEqual(ret.shared, 0)
self.assertEqual(ret.buffers, 0)
self.assertEqual(ret.available, 0)
self.assertEqual(ret.slab, 0)

def test_avail_old_percent(self):
# Make sure that our calculation of avail mem for old kernels
Expand Down