summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGiampaolo Rodola <g.rodola@gmail.com>2016-02-04 21:12:37 +0100
committerGiampaolo Rodola <g.rodola@gmail.com>2016-02-04 21:12:37 +0100
commitab4a66a6e942ba505bb5b0be6fefadeceaef6809 (patch)
treee0f14084e890a29d00a065a8cb1bcf530b71fa11
parentf670047cf99c9578b63c05c066c93befed6ff1cf (diff)
downloadpsutil-ab4a66a6e942ba505bb5b0be6fefadeceaef6809.tar.gz
provide a new memory_addrspace_info() fun and deprecate memory_info_ex
-rw-r--r--psutil/__init__.py45
-rw-r--r--psutil/_common.py19
-rw-r--r--psutil/_pslinux.py40
-rw-r--r--psutil/_psosx.py14
-rw-r--r--psutil/_pswindows.py24
-rw-r--r--test/_linux.py8
-rw-r--r--test/test_psutil.py53
7 files changed, 99 insertions, 104 deletions
diff --git a/psutil/__init__.py b/psutil/__init__.py
index be68951f..e53e918d 100644
--- a/psutil/__init__.py
+++ b/psutil/__init__.py
@@ -26,6 +26,7 @@ except ImportError:
pwd = None
from . import _common
+from ._common import deprecated_method
from ._common import memoize
from ._compat import callable
from ._compat import long
@@ -965,15 +966,14 @@ class Process(object):
"""
return self._proc.memory_info()
+ @deprecated_method(replacement="memory_info")
def memory_info_ex(self):
- """Return a namedtuple with variable fields depending on the
- platform representing extended memory information about
- this process. All numbers are expressed in bytes.
- """
- return self._proc.memory_info_ex()
+ return self.memory_info()
+
+ if hasattr(_psplatform.Process, "memory_addrspace_info"):
- def memory_info_addrspace(self):
- pass
+ def memory_addrspace_info(self):
+ return self._proc.memory_addrspace_info()
def memory_percent(self, memtype="rss"):
"""Compare process memory to total physical system memory and
@@ -982,20 +982,27 @@ class Process(object):
process memory you want to compare against (defaults to "rss").
The list of available strings can be obtained like this:
- >>> psutil.Process().memory_info_ex()._fields
+ >>> psutil.Process().memory_info()._fields
('rss', 'vms', 'shared', 'text', 'lib', 'data', 'dirty', 'uss', 'pss')
"""
- if memtype in ("rss", "vsz"):
- value = getattr(self.memory_info(), memtype)
+ if memtype in ('uss', 'pss'):
+ if not hasattr(self, "memory_addrspace_info"):
+ fields = _psplatform.pmem._fields
+ raise ValueError(
+ "invalid memtype %r; valid types are %r" % (
+ memtype, fields))
+ fun = self.memory_addrspace_info
+ fields = _psplatform.paddrspmem._fields
+
else:
- memex = self.memory_info_ex()
- if memtype not in memex._fields:
- raise ValueError("invalid memtype %r; valid types are %r" % (
- memtype, memex._fields))
- value = getattr(memex, memtype)
- if value == 0 and memtype in ('uss', 'pss'):
- raise AccessDenied(self.pid, self._name,
- msg="can't retrieve %s memory" % memtype)
+ fields = _psplatform.pmem._fields
+ fun = self.memory_info
+
+ if memtype not in fields:
+ raise ValueError("invalid memtype %r; valid types are %r" % (
+ memtype, fields))
+ metrics = fun()
+ value = getattr(metrics, memtype)
# use cached value if available
total_phymem = _TOTAL_PHYMEM or virtual_memory().total
@@ -1987,7 +1994,7 @@ def test(): # pragma: no cover
pinfo['name'].strip() or '?'))
-del memoize, division
+del memoize, division, deprecated_method
if sys.version_info < (3, 0):
del num
diff --git a/psutil/_common.py b/psutil/_common.py
index 78d59309..92b3b5e1 100644
--- a/psutil/_common.py
+++ b/psutil/_common.py
@@ -13,6 +13,7 @@ import os
import socket
import stat
import sys
+import warnings
from collections import namedtuple
from socket import AF_INET
from socket import SOCK_DGRAM
@@ -229,6 +230,24 @@ def socktype_to_enum(num):
return num
+def deprecated_method(replacement):
+ """A decorator which can be used to mark a method as deprecated
+ 'replcement' is the method name which will be called instead.
+ """
+ def outer(fun):
+ msg = "%s() is deprecated; use %s() instead" % (
+ fun.__name__, replacement)
+ if fun.__doc__ is None:
+ fun.__doc__ = msg
+
+ @functools.wraps(fun)
+ def inner(self, *args, **kwargs):
+ warnings.warn(msg, category=DeprecationWarning, stacklevel=2)
+ return getattr(self, replacement)(*args, **kwargs)
+ return inner
+ return outer
+
+
# --- Process.connections() 'kind' parameter mapping
conn_tmap = {
diff --git a/psutil/_pslinux.py b/psutil/_pslinux.py
index 22a95e58..8f54dfeb 100644
--- a/psutil/_pslinux.py
+++ b/psutil/_pslinux.py
@@ -219,7 +219,7 @@ svmem = namedtuple(
'active', 'inactive', 'buffers', 'cached'])
pmem = namedtuple('pmem', 'rss vms shared text lib data dirty')
-pextmem = namedtuple('pextmem', 'rss vms shared text lib data dirty uss pss')
+paddrspmem = namedtuple('paddrspmem', ['uss', 'pss'])
pmmap_grouped = namedtuple(
'pmmap_grouped', ['path', 'rss', 'size', 'pss', 'shared_clean',
@@ -970,35 +970,23 @@ class Process(object):
[int(x) * PAGESIZE for x in f.readline().split()[:7]]
return pmem(rss, vms, shared, text, lib, data, dirty)
- @wrap_exceptions
- def memory_info_ex(self,
- _private_re=re.compile(b"Private.*:\s+(\d+)"),
- _pss_re=re.compile(b"Pss.*:\s+(\d+)")):
- base_mem = self.memory_info()
- uss = pss = 0
- if HAS_SMAPS:
+ if HAS_SMAPS:
+
+ @wrap_exceptions
+ def memory_addrspace_info(
+ self,
+ _private_re=re.compile(b"Private.*:\s+(\d+)"),
+ _pss_re=re.compile(b"Pss.*:\s+(\d+)")):
# Note: using two regexes is faster than reading the file
# line by line.
# XXX: on Python 3 the 2 regexes are 30% slower than on
# Python 2 though. Figure out why.
- try:
- with open_binary("%s/%s/smaps" % (self._procfs_path, self.pid),
- buffering=BIGGER_FILE_BUFFERING) as f:
- smaps_data = f.read()
- except EnvironmentError as err:
- if err.errno not in (errno.EPERM, errno.EACCES):
- raise
- else:
- uss = sum(map(int, _private_re.findall(smaps_data))) * 1024
- pss = sum(map(int, _pss_re.findall(smaps_data))) * 1024
- else:
- # usually means we're on kernel < 2.6.14 or CONFIG_MMU kernel
- # configuration option is not enabled.
- pass
-
- return pextmem(*base_mem + (uss, pss))
-
- if HAS_SMAPS:
+ with open_binary("%s/%s/smaps" % (self._procfs_path, self.pid),
+ buffering=BIGGER_FILE_BUFFERING) as f:
+ smaps_data = f.read()
+ uss = sum(map(int, _private_re.findall(smaps_data))) * 1024
+ pss = sum(map(int, _pss_re.findall(smaps_data))) * 1024
+ return paddrspmem(uss, pss)
@wrap_exceptions
def memory_maps(self):
diff --git a/psutil/_psosx.py b/psutil/_psosx.py
index e78f8784..e3439dde 100644
--- a/psutil/_psosx.py
+++ b/psutil/_psosx.py
@@ -59,7 +59,7 @@ svmem = namedtuple(
'active', 'inactive', 'wired'])
pmem = namedtuple('pextmem', ['rss', 'vms', 'pfaults', 'pageins'])
-pextmem = namedtuple('pextmem', ['rss', 'vms', 'pfaults', 'pageins', 'uss'])
+paddrspmem = namedtuple('paddrspmem', ['uss', 'pss'])
pmmap_grouped = namedtuple(
'pmmap_grouped',
@@ -274,15 +274,9 @@ class Process(object):
return pmem(rss, vms, pfaults, pageins)
@wrap_exceptions
- def memory_info_ex(self):
- base_mem = self.memory_info()
- uss = 0
- try:
- uss = cext.proc_memory_uss(self.pid)
- except OSError as err:
- if err.errno not in (errno.EPERM, errno.EACCES):
- raise
- return pextmem(*base_mem + (uss, ))
+ def memory_addrspace_info(self):
+ uss = cext.proc_memory_uss(self.pid)
+ return paddrspmem(uss)
@wrap_exceptions
def cpu_times(self):
diff --git a/psutil/_pswindows.py b/psutil/_pswindows.py
index 9635a3d4..a9167551 100644
--- a/psutil/_pswindows.py
+++ b/psutil/_pswindows.py
@@ -84,10 +84,11 @@ if enum is not None:
scputimes = namedtuple('scputimes', ['user', 'system', 'idle'])
svmem = namedtuple('svmem', ['total', 'available', 'percent', 'used', 'free'])
-pextmem = namedtuple(
- 'pextmem', ['num_page_faults', 'peak_wset', 'wset', 'peak_paged_pool',
- 'paged_pool', 'peak_nonpaged_pool', 'nonpaged_pool',
- 'pagefile', 'peak_pagefile', 'private', 'uss'])
+pmem = namedtuple(
+ 'pmem', ['num_page_faults', 'peak_wset', 'wset', 'peak_paged_pool',
+ 'paged_pool', 'peak_nonpaged_pool', 'nonpaged_pool',
+ 'pagefile', 'peak_pagefile', 'private'])
+paddrspmem = namedtuple('paddrspmem', ['uss'])
pmmap_grouped = namedtuple('pmmap_grouped', ['path', 'rss'])
pmmap_ext = namedtuple(
'pmmap_ext', 'addr perms ' + ' '.join(pmmap_grouped._fields))
@@ -359,14 +360,6 @@ class Process(object):
return cext.proc_memory_info_2(self.pid)
raise
- def _get_uss_mem(self):
- try:
- return cext.proc_memory_uss(self.pid)
- except OSError as err:
- if err.errno in ACCESS_DENIED_SET:
- return 0
- raise
-
@wrap_exceptions
def memory_info(self):
# on Windows RSS == WorkingSetSize and VSM == PagefileUsage
@@ -377,10 +370,9 @@ class Process(object):
return _common.pmem(t[2], t[7])
@wrap_exceptions
- def memory_info_ex(self):
- info = self._get_raw_meminfo()
- uss = self._get_uss_mem()
- return pextmem(*info + (uss, ))
+ def memory_addrspace_info(self):
+ uss = cext.proc_memory_uss(self.pid)
+ return paddrspmem(uss)
def memory_maps(self):
try:
diff --git a/test/_linux.py b/test/_linux.py
index 637ad1f7..cebd21a4 100644
--- a/test/_linux.py
+++ b/test/_linux.py
@@ -599,7 +599,7 @@ class LinuxSpecificTestCase(unittest.TestCase):
self.assertEqual(psutil.Process().exe(), "/home/foo")
self.assertEqual(psutil.Process().cwd(), "/home/foo")
- def test_uss_pss_mem_against_mem_maps(self):
+ def test_memory_addrspace_info(self):
src = textwrap.dedent("""
import time
with open("%s", "w") as f:
@@ -610,12 +610,12 @@ class LinuxSpecificTestCase(unittest.TestCase):
call_until(lambda: os.listdir('.'), "'%s' not in ret" % TESTFN)
p = psutil.Process(sproc.pid)
time.sleep(.1)
- memex = p.memory_info_ex()
+ mem = p.memory_addrspace_info()
maps = p.memory_maps(grouped=False)
self.assertEqual(
- memex.uss, sum([x.private_dirty + x.private_clean for x in maps]))
+ mem.uss, sum([x.private_dirty + x.private_clean for x in maps]))
self.assertEqual(
- memex.pss, sum([x.shared_dirty + x.shared_clean for x in maps]))
+ mem.pss, sum([x.pss for x in maps]))
def main():
diff --git a/test/test_psutil.py b/test/test_psutil.py
index 9bd6eddf..e8017cf3 100644
--- a/test/test_psutil.py
+++ b/test/test_psutil.py
@@ -1685,22 +1685,21 @@ class TestProcess(unittest.TestCase):
rss2, vms2 = p.memory_info()[:2]
percent2 = p.memory_percent()
- # make sure that the memory usage bumped up
+
+ # step 3 - make sure that the memory usage bumped up
self.assertGreater(rss2, rss1)
self.assertGreaterEqual(vms2, vms1) # vms might be equal
self.assertGreater(percent2, percent1)
del memarr
- def test_memory_info_ex(self):
- memex = psutil.Process().memory_info_ex()
- if LINUX or OSX or WINDOWS:
- self.assertGreater(memex.uss, 0)
- if LINUX:
- self.assertGreater(memex.pss, 0)
- self.assertGreater(memex.pss, memex.uss)
- base_mem = psutil.Process().memory_info()
- self.assertEqual(memex.rss, base_mem.rss)
- self.assertEqual(memex.vms, base_mem.vms)
+ @unittest.skipUnless(LINUX or OSX or WINDOWS,
+ "not available on this platform")
+ def test_memory_addrspace_info(self):
+ mem = psutil.Process().memory_addrspace_info()
+ self.assertGreater(mem.uss, 0)
+ if LINUX:
+ self.assertGreater(mem.pss, 0)
+ self.assertGreater(mem.pss, mem.uss)
@unittest.skipIf(OPENBSD or NETBSD, "not available on this platform")
def test_memory_maps(self):
@@ -1739,20 +1738,12 @@ class TestProcess(unittest.TestCase):
assert 0 <= ret <= 100, ret
ret = p.memory_percent(memtype='vms')
assert 0 <= ret <= 100, ret
- memtype = psutil._psplatform.pextmem._fields[-1]
- ret = p.memory_percent(memtype=memtype)
assert 0 <= ret <= 100, ret
self.assertRaises(ValueError, p.memory_percent, memtype="?!?")
-
- @unittest.skipUnless(LINUX or OSX or WINDOWS,
- "uss not available on this plaftorm")
- def test_memory_percent_uss_ad(self):
- ret = collections.namedtuple("pextm", "rss vms uss")(1, 1, 0)
- with mock.patch("psutil._psplatform.Process.memory_info_ex",
- return_value=ret):
- p = psutil.Process()
- self.assertRaises(
- psutil.AccessDenied, p.memory_percent, memtype="uss")
+ if LINUX or OSX or WINDOWS:
+ ret = p.memory_percent(memtype='uss')
+ assert 0 <= ret <= 100, ret
+ assert 0 <= ret <= 100, ret
def test_is_running(self):
sproc = get_test_subprocess(wait=True)
@@ -2603,7 +2594,9 @@ class TestFetchAllProcesses(unittest.TestCase):
valid_procs = 0
excluded_names = set([
'send_signal', 'suspend', 'resume', 'terminate', 'kill', 'wait',
- 'as_dict', 'cpu_percent', 'parent', 'children', 'pid'])
+ 'as_dict', 'cpu_percent', 'parent', 'children', 'pid',
+ 'memory_info_ex',
+ ])
if LINUX and not RLIMIT_SUPPORT:
excluded_names.add('rlimit')
attrs = []
@@ -2753,12 +2746,8 @@ class TestFetchAllProcesses(unittest.TestCase):
self.assertTrue(ret.system >= 0)
def memory_info(self, ret, proc):
- self.assertTrue(ret.rss >= 0)
- self.assertTrue(ret.vms >= 0)
-
- def memory_info_ex(self, ret, proc):
for name in ret._fields:
- self.assertTrue(getattr(ret, name) >= 0)
+ self.assertGreaterEqual(getattr(ret, name), 0)
if POSIX and ret.vms != 0:
# VMS is always supposed to be the highest
for name in ret._fields:
@@ -2771,6 +2760,12 @@ class TestFetchAllProcesses(unittest.TestCase):
assert ret.peak_nonpaged_pool >= ret.nonpaged_pool, ret
assert ret.peak_pagefile >= ret.pagefile, ret
+ def memory_addrspace_info(self, ret, proc):
+ for name in ret._fields:
+ self.assertGreaterEqual(getattr(ret, name), 0)
+ if LINUX:
+ self.assertGreaterEqual(ret.pss, ret.uss)
+
def open_files(self, ret, proc):
for f in ret:
if WINDOWS: