-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathcmn_traffic_gen.py
129 lines (113 loc) · 4.04 KB
/
cmn_traffic_gen.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
#!/usr/bin/python3
"""
Generate traffic from a CPU
Copyright (C) Arm Ltd. 2024. All rights reserved.
SPDX-License-Identifier: Apache 2.0
"""
from __future__ import print_function
import sys
import os
import subprocess
import tempfile
import atexit
o_verbose = 0
o_lmbench = None
# Traffic generation. We need to generate a rapid stream of traffic to the
# interconnect, which can then be detected by measurement.
# The easiest way to generate traffic is to read a large memory buffer.
# We either use a small C program, or (if provided), lmbench bw_mem.
# The user can supply an approximate run time for each measurement.
# (1 second is usually enough). The time doesn't need to be accurate,
# so we haven't bothered setting up a calibration phase - the factors
# in the loop counts below should give reasonable results.
_gen_c = """
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
int main(int argc, char **argv)
{
long N = atol(argv[1]);
long size_M = atol(argv[2]);
size_t sz = size_M << 20;
long i;
int x = 0;
int volatile *m = (int *)malloc(sz);
memset((void *)m, 0xcc, sz); /* avoid sharing a zero page */
fprintf(stderr, "generating load %luMb\\n", size_M); /* match lmbench */
for (i = 0; i < N*12; ++i) {
long j;
for (j = 0; j < size_M*1024*1024/sizeof(int); j += 4) {
x += m[j];
}
}
return x;
}
"""
g_generator_exe = None
def _gen_generator():
global g_generator_exe
if g_generator_exe is not None:
return g_generator_exe
(fd, g_generator_exe) = tempfile.mkstemp(suffix=".exe")
os.close(fd)
atexit.register(os.remove, g_generator_exe)
cmd = "cc -O2 -Wall -Werror -xc - -o %s" % (g_generator_exe)
if o_verbose:
print(">>> %s" % cmd, file=sys.stderr)
p = subprocess.Popen(cmd.split(), stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
p.stdin.write(_gen_c.encode())
(out, err) = p.communicate()
if p.returncode != 0:
print("compiler out: %s" % out)
print("compiler err: %s" % err)
sys.exit(1)
return g_generator_exe
def cpu_gen_traffic(cpu, events=["instructions"], time=0.1, size_M=16):
"""
Generate traffic, and return performance events
"""
if o_lmbench is not None:
cmd = "%s/bw_mem -N %u %uM rd" % (o_lmbench, int(time*100), size_M)
else:
exe = _gen_generator()
cmd = "%s %u %u" % (exe, int(time*100), size_M)
if cpu is not None:
cmd = "taskset -c %u %s" % (cpu, cmd)
if events:
elist = ",".join(events)
cmd = "perf stat -x, -e %s -- %s" % (elist, cmd)
if o_verbose >= 2:
print(">>> %s" % cmd, file=sys.stderr)
p = subprocess.Popen(cmd.split(), stdout=subprocess.PIPE, stderr=subprocess.PIPE)
(out, err) = p.communicate()
if o_verbose >= 2:
print("out: %s" % out, file=sys.stderr)
print("err: %s" % err, file=sys.stderr)
if p.returncode != 0:
print("%s" % err.decode(), file=sys.stderr)
sys.exit(1)
if not events:
return []
elines = err.decode().split('\n')
ecounts = []
for e in elines[1:]: # first line is lmbench output, skip it
if not e:
continue
f = e.split(',')
r = int(f[0])
ecounts.append(r)
if o_verbose >= 2:
print("counts: %s" % (ecounts))
return ecounts
if __name__ == "__main__":
import argparse
parser = argparse.ArgumentParser(description="generate traffic from CPU")
parser.add_argument("--cpu", type=int, help="pin generator to CPU")
parser.add_argument("--time", type=float, default=1.0, help="approximate run time")
parser.add_argument("--size", type=int, default=16, help="workload size in Mb")
parser.add_argument("--lmbench-bin", type=str, default=None, help="path to lmbench bin")
parser.add_argument("-v", "--verbose", action="count", default=0, help="increase verbosity")
opts = parser.parse_args()
o_verbose = opts.verbose
o_lmbench = opts.lmbench_bin
cpu_gen_traffic(opts.cpu, time=opts.time, size_M=opts.size)