Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
eclipse
GitHub Repository: eclipse/sumo
Path: blob/main/tools/devel/timing.py
169673 views
1
#!/usr/bin/env python
2
# Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
3
# Copyright (C) 2011-2025 German Aerospace Center (DLR) and others.
4
# This program and the accompanying materials are made available under the
5
# terms of the Eclipse Public License 2.0 which is available at
6
# https://www.eclipse.org/legal/epl-2.0/
7
# This Source Code may also be made available under the following Secondary
8
# Licenses when the conditions for such availability set forth in the Eclipse
9
# Public License 2.0 are satisfied: GNU General Public License, version 2
10
# or later which is available at
11
# https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html
12
# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later
13
14
# @file timing.py
15
# @author Michael Behrisch
16
# @date 2018-11-30
17
18
"""
19
This script uses either a directory with historic sumo versions
20
or git bisect to compare performance of different sumo versions.
21
"""
22
from __future__ import absolute_import
23
from __future__ import print_function
24
25
import subprocess
26
import argparse
27
import os
28
import sys
29
import collections
30
import numpy
31
32
33
def build():
34
sumoSubdir = False
35
if os.path.exists(os.path.join("sumo", "src", "sumo_main.cpp")):
36
os.chdir("sumo")
37
sumoSubdir = True
38
subprocess.check_call(["make", "-j"])
39
if sumoSubdir:
40
os.chdir("..")
41
return "sumo"
42
return ""
43
44
45
def runHistory(args, versions, extraInfo=""):
46
results = collections.defaultdict(list)
47
for d in versions:
48
command = ['/usr/bin/time', '-v', os.path.join(d, 'bin', 'sumo'), "-v", "-c", args.cfg]
49
try:
50
for _ in range(args.runs):
51
for ol in subprocess.check_output(command, stderr=subprocess.STDOUT).splitlines():
52
if "User time" in ol:
53
t = float(ol.split(": ")[-1]) # noqa
54
elif "wall clock" in ol:
55
w = float(ol.split(":")[-1]) # noqa
56
elif "UPS: " in ol:
57
u = 1e6 / max(1., float(ol.split(": ")[-1])) # noqa
58
elif "Maximum resident" in ol:
59
m = float(ol.split(": ")[-1]) # noqa
60
# adapt the return values as needed below
61
results[d].append((u, t))
62
except subprocess.CalledProcessError as err:
63
if len(versions) == 1:
64
raise
65
else:
66
print(err, file=sys.stderr)
67
continue
68
with open(args.stats, "a") as out:
69
for d, r in sorted(results.items()):
70
r = sorted(r)[:args.runs - args.skip]
71
print(d, extraInfo, " ".join(map(str, numpy.mean(r, 0))), file=out)
72
return numpy.mean(r, 0)[0]
73
74
75
argparser = argparse.ArgumentParser()
76
argparser.add_argument("cfg", help="sumo config to run")
77
argparser.add_argument("--versions", nargs="*", help="sumo versions to run")
78
argparser.add_argument("--stats", help="stats file to write")
79
argparser.add_argument("--basedir", default="buildHistory", help="where to find the version subdirs")
80
argparser.add_argument("--bisect", type=float, help="run git bisect with the given threshold value")
81
argparser.add_argument("--runs", type=int, default=5, help="number of runs for each version")
82
argparser.add_argument("--skip", type=int, default=2, help="number of worst runs to skip for each version")
83
args = argparser.parse_args()
84
if args.stats is None:
85
args.stats = os.path.dirname(args.cfg) + ".stats"
86
if args.skip >= args.runs:
87
args.skip = args.runs // 2
88
print("Skipping too many runs, reducing skip to %s." % args.skip, file=sys.stderr)
89
if args.versions:
90
versions = args.versions
91
else:
92
versions = [os.path.join(args.basedir, v) for v in os.listdir(args.basedir)]
93
if args.bisect:
94
versions = [build()]
95
96
if args.bisect:
97
try:
98
time = runHistory(args, versions, subprocess.check_output(["git", "describe", "--always"]).strip())
99
except subprocess.CalledProcessError as e:
100
print(e, file=sys.stderr)
101
sys.exit(125) # an exit code of 125 asks "git bisect" to "skip" the current commit
102
# subprocess.call(["git", "reset", "--hard"]) # to allow bisect to continue even when there are local modifications
103
sys.exit(0 if time < args.bisect else 1)
104
else:
105
runHistory(args, versions)
106
107