-
-
Notifications
You must be signed in to change notification settings - Fork 1.4k
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
Improve CPU time resolution #1461
Comments
Uhm... we collect that value from /proc/pid/stat (which looks like 117), then we divide it by CLOCK_TICKS, which is 100, hence the reason why this has XX digits precision. No idea how |
Interestingly it appears that the bash builtin |
Interesting. We should look at the source code of these tools. |
This page is a good resource that explains why bash's built-in "time" is more precise than /usr/bin/time, and which calls these tools use to get the results: https://gist.github.com/linse/3737870 |
Having maxrss as a measurement of the peak memory usage (which appears to be in getrusage) would also be pretty handy though. An alternative that would work for me would be a tiny C wrapper that executes the program and reports the getrusage() result at the end back to the python program, and I might end up writing that instead. Would not be a general solution that would fit into psutil though. |
@wiggin15 thanks a lot for finding that out. The difference is indeed import psutil, resource
p = psutil.Process()
# warm up
for x in range(10000000):
pass
for x in range(5):
a = p.cpu_times()
b = resource.getrusage(resource.RUSAGE_SELF)
print(a.user, a.system)
print(b.ru_utime, b.ru_stime) Which prints:
Some considerations:
>>> psutil.Process().cpu_times()
pcputimes(user=0.1, system=0.01, children_user=0.0, children_system=0.0)
|
Putting this here for now and I'll get back to it later: diff --git a/psutil/__init__.py b/psutil/__init__.py
index ab2ed349..b3680bfb 100644
--- a/psutil/__init__.py
+++ b/psutil/__init__.py
@@ -37,6 +37,10 @@ try:
import pwd
except ImportError:
pwd = None
+try:
+ import resource
+except ImportError:
+ resource = None
from . import _common
from ._common import deprecated_method
@@ -226,6 +230,7 @@ POWER_TIME_UNLIMITED = _common.POWER_TIME_UNLIMITED
POWER_TIME_UNKNOWN = _common.POWER_TIME_UNKNOWN
_TOTAL_PHYMEM = None
_LOWEST_PID = None
+_THIS_PID = os.getpid()
# Sanity check in case the user messed up with psutil installation
# or did something weird with sys.path. In this case we might end
@@ -1152,7 +1157,21 @@ class Process(object):
On macOS and Windows children_user and children_system are
always set to 0.
"""
- return self._proc.cpu_times()
+ if self.pid == _THIS_PID and resource is not None:
+ # better precision
+ t = resource.getrusage(resource.RUSAGE_SELF)
+ utime, stime = t.ru_utime, t.ru_stime
+ children_utime, children_stime = 0, 0
+ if hasattr(resource, "RUSAGE_CHILDREN"):
+ t = resource.getrusage(resource.RUSAGE_CHILDREN)
+ children_utime, children_stime = t.ru_utime, t.ru_stime
+ else:
+ t = self._proc.cpu_times()
+ children_utime, children_stime = t[2], t[3]
+ return _common.pcputimes(
+ utime, stime, children_utime, children_stime)
+ else:
+ return self._proc.cpu_times()
@memoize_when_activated
def memory_info(self): |
The resolution of the CPU times seems to be artificially limited to 2 decimal places. For example:
In fact it seems impossible to get more than 2 decimals from psutil.
But using the built in bash function on Linux I get 3 decimal places:
There doesn't seem to be a good reason to artificially limit the precision of returned values (in decimal even!), when they might not be printed, but used by a program, such as for benchmarking.
The text was updated successfully, but these errors were encountered: