summaryrefslogtreecommitdiff
path: root/scripts
diff options
context:
space:
mode:
authorGiampaolo Rodola <g.rodola@gmail.com>2022-10-20 22:38:18 +0200
committerGiampaolo Rodola <g.rodola@gmail.com>2022-10-20 22:38:18 +0200
commit085691ac46b060aeb6d17a202fcc33062f61d9b5 (patch)
treed49978ba82a587cca5060617d093290fd6ee6866 /scripts
parent1da9f7928e79ecc127768e7a5bc4eb7f785f4513 (diff)
downloadpsutil-085691ac46b060aeb6d17a202fcc33062f61d9b5.tar.gz
improve API speed benchmark script #2102
Diffstat (limited to 'scripts')
-rwxr-xr-xscripts/internal/print_api_speed.py147
1 files changed, 118 insertions, 29 deletions
diff --git a/scripts/internal/print_api_speed.py b/scripts/internal/print_api_speed.py
index ee2e3254..f41d0466 100755
--- a/scripts/internal/print_api_speed.py
+++ b/scripts/internal/print_api_speed.py
@@ -4,30 +4,75 @@
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
-"""Benchmark all API calls.
+"""
+Benchmark all API calls and print them from fastest to slowest.
$ make print_api_speed
-SYSTEM APIS SECONDS
-----------------------------------
-cpu_count 0.000014
-disk_usage 0.000027
-cpu_times 0.000037
-cpu_percent 0.000045
-...
-
-PROCESS APIS SECONDS
-----------------------------------
-create_time 0.000001
-nice 0.000005
-cwd 0.000011
-cpu_affinity 0.000011
-ionice 0.000013
-...
+SYSTEM APIS NUM CALLS SECONDS
+-------------------------------------------------
+disk_usage 300 0.00157
+cpu_count 300 0.00255
+pid_exists 300 0.00792
+cpu_times 300 0.01044
+boot_time 300 0.01136
+cpu_percent 300 0.01290
+cpu_times_percent 300 0.01515
+virtual_memory 300 0.01594
+users 300 0.01964
+net_io_counters 300 0.02027
+cpu_stats 300 0.02034
+net_if_addrs 300 0.02962
+swap_memory 300 0.03209
+sensors_battery 300 0.05186
+pids 300 0.07954
+net_if_stats 300 0.09321
+disk_io_counters 300 0.09406
+cpu_count (cores) 300 0.10293
+disk_partitions 300 0.10345
+cpu_freq 300 0.20817
+sensors_fans 300 0.63476
+sensors_temperatures 231 2.00039
+process_iter (all) 171 2.01300
+net_connections 97 2.00206
+
+PROCESS APIS NUM CALLS SECONDS
+-------------------------------------------------
+create_time 300 0.00009
+exe 300 0.00015
+nice 300 0.00057
+ionice 300 0.00091
+cpu_affinity 300 0.00091
+cwd 300 0.00151
+num_fds 300 0.00391
+memory_info 300 0.00597
+memory_percent 300 0.00648
+io_counters 300 0.00707
+name 300 0.00894
+status 300 0.00900
+ppid 300 0.00906
+num_threads 300 0.00932
+cpu_num 300 0.00933
+num_ctx_switches 300 0.00943
+uids 300 0.00979
+gids 300 0.01002
+cpu_times 300 0.01008
+cmdline 300 0.01009
+terminal 300 0.01059
+is_running 300 0.01063
+threads 300 0.01209
+connections 300 0.01276
+cpu_percent 300 0.01463
+open_files 300 0.01630
+username 300 0.01655
+environ 300 0.02250
+memory_full_info 300 0.07066
+memory_maps 300 0.74281
"""
from __future__ import division
from __future__ import print_function
+import argparse
import inspect
import os
from timeit import default_timer as timer
@@ -36,16 +81,23 @@ import psutil
from psutil._common import print_color
+TIMES = 300
timings = []
-templ = "%-25s %s"
+templ = "%-25s %10s %10s"
+
+
+def print_header(what):
+ s = templ % (what, "NUM CALLS", "SECONDS")
+ print_color(s, color=None, bold=True)
+ print("-" * len(s))
def print_timings():
- timings.sort(key=lambda x: x[1])
+ timings.sort(key=lambda x: (x[1], -x[2]), reverse=True)
i = 0
while timings[:]:
- title, elapsed = timings.pop(0)
- s = templ % (title, "%f" % elapsed)
+ title, times, elapsed = timings.pop(0)
+ s = templ % (title, str(times), "%.5f" % elapsed)
if i > len(timings) - 5:
print_color(s, color="red")
else:
@@ -53,13 +105,48 @@ def print_timings():
def timecall(title, fun, *args, **kw):
+ print("%-50s" % title, end="", flush=True)
t = timer()
- fun(*args, **kw)
- elapsed = timer() - t
- timings.append((title, elapsed))
+ for n in range(TIMES):
+ fun(*args, **kw)
+ elapsed = timer() - t
+ if elapsed > 2:
+ break
+ print("\r", end="", flush=True)
+ timings.append((title, n + 1, elapsed))
+
+
+def set_highest_priority():
+ """Set highest CPU and I/O priority (requires root)."""
+ p = psutil.Process()
+ if psutil.WINDOWS:
+ p.nice(psutil.HIGH_PRIORITY_CLASS)
+ else:
+ p.nice(-20)
+
+ if psutil.LINUX:
+ p.ionice(psutil.IOPRIO_CLASS_RT, value=7)
+ elif psutil.WINDOWS:
+ p.ionice(psutil.IOPRIO_HIGH)
def main():
+ global TIMES
+
+ parser = argparse.ArgumentParser(
+ description=__doc__, formatter_class=argparse.RawTextHelpFormatter)
+ parser.add_argument('-t', '--times', type=int, default=TIMES)
+ args = parser.parse_args()
+ TIMES = args.times
+ assert TIMES > 1, TIMES
+
+ try:
+ set_highest_priority()
+ except psutil.AccessDenied:
+ prio_set = False
+ else:
+ prio_set = True
+
# --- system
public_apis = []
@@ -73,8 +160,7 @@ def main():
if name not in ignore:
public_apis.append(name)
- print_color(templ % ("SYSTEM APIS", "SECONDS"), color=None, bold=True)
- print("-" * 34)
+ print_header("SYSTEM APIS")
for name in public_apis:
fun = getattr(psutil, name)
args = ()
@@ -89,11 +175,10 @@ def main():
# --- process
print("")
- print_color(templ % ("PROCESS APIS", "SECONDS"), color=None, bold=True)
- print("-" * 34)
+ print_header("PROCESS APIS")
ignore = ['send_signal', 'suspend', 'resume', 'terminate', 'kill', 'wait',
'as_dict', 'parent', 'parents', 'memory_info_ex', 'oneshot',
- 'pid', 'rlimit']
+ 'pid', 'rlimit', 'children']
if psutil.MACOS:
ignore.append('memory_maps') # XXX
p = psutil.Process()
@@ -103,6 +188,10 @@ def main():
timecall(name, fun)
print_timings()
+ if not prio_set:
+ print_color("\nWARN: couldn't set highest process priority " +
+ "(requires root)", "red")
+
if __name__ == '__main__':
main()