e1506a86e25d35b17be3eafd4b9b33edcd22a487
2 # Copyright (C) 2019 - Jonathan Rajotte Julien <jonathan.rajotte-julien@efficios.com>
4 # This program is free software: you can redistribute it and/or modify
5 # it under the terms of the GNU General Public License as published by
6 # the Free Software Foundation, either version 3 of the License, or
7 # (at your option) any later version.
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
14 # You should have received a copy of the GNU General Public License
15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
22 from collections
import defaultdict
25 "User time (seconds)": float,
26 "System time (seconds)": float,
27 "Percent of CPU this job got": percent_parser
,
28 "Elapsed (wall clock) time (h:mm:ss or m:ss)": wall_clock_parser
,
29 "Average shared text size (kbytes)": int,
30 "Average unshared data size (kbytes)": int,
31 "Average stack size (kbytes)": int,
32 "Average total size (kbytes)": int,
33 "Maximum resident set size (kbytes)": int,
34 "Average resident set size (kbytes)": int,
35 "Major (requiring I/O) page faults": int,
36 "Minor (reclaiming a frame) page faults": int,
37 "Voluntary context switches": int,
38 "Involuntary context switches": int,
40 "File system inputs": int,
41 "File system outputs": int,
42 "Socket messages sent": int,
43 "Socket messages received": int,
44 "Signals delivered": int,
45 "Page size (bytes)": int,
49 def wall_clock_parser(value
):
51 Parse /usr/bin/time wall clock value.
52 Wall clock value is expressed in different formats depending on the actual
58 total
+= float(value
[pos
:])
61 v_split
= value
.split(":")
63 total
+= float(v_split
[0]) * 60.0
64 total
+= float(v_split
[1]) * 1.0
65 elif len(v_split
) == 3:
66 total
+= float(v_split
[0]) * 360.0
67 total
+= float(v_split
[1]) * 60.0
68 total
+= float(v_split
[2]) * 1.0
75 def percent_parser(value
):
77 Parse /usr/bin/time percent value.
79 parsed
= value
.replace("%", "").replace("?", "")
85 def parse(path
, results
):
87 Parser and accumulator for /usr/bin/time results.
89 with
open(path
, "r") as data
:
91 if line
.rfind(":") == -1:
93 key
, value
= line
.lstrip().rsplit(": ")
95 results
[key
].append(_METRIC
[key
](value
))
100 def save(path
, results
):
102 Save the result in json format to path.
104 with
open(path
, "w") as out
:
105 json
.dump(results
, out
, sort_keys
=True, indent
=4)
108 def run(command
, iteration
, output
, stdout
, stderr
):
110 Run the command throught /usr/bin/time n iterations and parse each result.
112 results
= defaultdict(list)
113 for i
in range(iteration
):
114 time_stdout
= tempfile
.NamedTemporaryFile(delete
=False)
115 # We must delete this file later on.
117 with
open(stdout
, "a+") as out
, open(stderr
, "a+") as err
:
118 cmd
= "/usr/bin/time -v --output='{}' {}".format(time_stdout
.name
, command
)
119 ret
= subprocess
.run(cmd
, shell
=True, stdout
=out
, stderr
=err
)
120 if ret
.returncode
!= 0:
121 print("Iteration: {}, Command failed: {}".format(str(i
), cmd
))
122 results
= parse(time_stdout
.name
, results
)
123 os
.remove(time_stdout
.name
)
124 save(output
, results
)
129 Run /usr/bin/time N time and collect the result.
130 The resulting json have the following form:
133 "User time (seconds)": [],
134 "System time (seconds)": [],
135 "Percent of CPU this job got": [],
136 "Elapsed (wall clock) time (h:mm:ss or m:ss)": [],
137 "Average shared text size (kbytes)": [],
138 "Average unshared data size (kbytes)": [],
139 "Average stack size (kbytes)": [],
140 "Average total size (kbytes)": [],
141 "Maximum resident set size (kbytes)": [],
142 "Average resident set size (kbytes)": [],
143 "Major (requiring I/O) page faults": [],
144 "Minor (reclaiming a frame) page faults": [],
145 "Voluntary context switches": [],
146 "Involuntary context switches": [],
148 "File system inputs": [],
149 "File system outputs": [],
150 "Socket messages sent": [],
151 "Socket messages received": [],
152 "Signals delivered": [],
153 "Page size (bytes)": [],
157 parser
= argparse
.ArgumentParser(
158 description
="Run command N time using /usr/bin/time and collect the statistics"
160 parser
.add_argument("--output", help="Where to same the result", required
=True)
161 parser
.add_argument("--command", help="The command to benchmark", required
=True)
166 help="The number of iteration to run the command (default: 5)",
172 help="Where to append the stdout of each command (default: /dev/null)",
176 default
=os
.path
.join(os
.getcwd(), "stderr.out"),
177 help="Where to append the stderr of each command (default: $CWD/stderr.out)",
180 args
= parser
.parse_args()
181 run(args
.command
, args
.iteration
, args
.output
, args
.stdout
, args
.stderr
)
184 if __name__
== "__main__":
This page took 0.035686 seconds and 3 git commands to generate.