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
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
| | #!/bin/sh
#
# SPDX-License-Identifier: GPL-2.0-or-later
#
# PASST - Plug A Simple Socket Transport
# for qemu/UNIX domain socket mode
#
# PASTA - Pack A Subtle Tap Abstraction
# for network namespace/tap device mode
#
# test/lib/perf_report - Prepare JavaScript report for performance tests
#
# Copyright (c) 2021 Red Hat GmbH
# Author: Stefano Brivio <sbrivio@redhat.com>
PERF_INIT=0
PERF_LINK_COUNT=0
PERF_JS="${LOGDIR}/web/perf.js"
PERF_TEMPLATE_HTML="document.write('"'
Throughput in Gbps, latency in µs. Threads are <span style="font-family: monospace;">iperf3</span> threads, <i>passt</i> and <i>pasta</i> are currently single-threaded.<br/>
Click on numbers to show test execution. Measured at head, commit <span style="font-family: monospace;">__commit__</span>.
<style type="text/CSS">
table.passt td { border: 0px solid; padding: 6px; line-height: 1; }
table.passt td { text-align: right; }
table.passt th { text-align: center; font-weight: bold; }
table.passt tr:not(:first-of-type) td:not(:first-of-type) { font-family: monospace; font-weight: bolder; }
table.passt tr:nth-child(3n+0) { background-color: #112315; }
table.passt tr:not(:nth-child(3n+0)) td { background-color: #101010; }
table.passt td:nth-child(6n+7) { background-color: #603302; }
table.passt tr:nth-child(1) { background-color: #363e61; }
td:empty { visibility: hidden; }
</style>
<ul>
<li><p>passt</p>
<table class="passt" width="70%">
<tr>
<th/>
<th id="perf_passt_tcp" colspan="__passt_tcp_cols__">TCP, __passt_tcp_threads__ at __passt_tcp_freq__ GHz</th>
<th id="perf_passt_udp" colspan="__passt_udp_cols__">UDP, __passt_udp_threads__ at __passt_udp_freq__ GHz</th>
</tr>
<tr>
<td align="right">MTU:</td>
__passt_tcp_header__
__passt_udp_header__
</tr>
__passt_tcp_LINE__ __passt_udp_LINE__
</table>
</li><li><p>passt with vhost-user support</p>
<table class="passt" width="70%">
<tr>
<th/>
<th id="perf_passt_vu_tcp" colspan="__passt_vu_tcp_cols__">TCP, __passt_vu_tcp_threads__ at __passt_vu_tcp_freq__ GHz</th>
<th id="perf_passt_vu_udp" colspan="__passt_vu_udp_cols__">UDP, __passt_vu_udp_threads__ at __passt_vu_udp_freq__ GHz</th>
</tr>
<tr>
<td align="right">MTU:</td>
__passt_vu_tcp_header__
__passt_vu_udp_header__
</tr>
__passt_vu_tcp_LINE__ __passt_vu_udp_LINE__
</table>
<style type="text/CSS">
table.pasta_local td { border: 0px solid; padding: 6px; line-height: 1; }
table.pasta_local td { text-align: right; }
table.pasta_local th { text-align: center; font-weight: bold; }
table.pasta_local tr:not(:first-of-type) td:not(:first-of-type) { font-family: monospace; font-weight: bolder; }
table.pasta_local tr:nth-child(3n+0) { background-color: #112315; }
table.pasta_local tr:not(:nth-child(3n+0)) td { background-color: #101010; }
table.pasta_local td:nth-child(4n+2) { background-color: #603302; }
table.pasta_local tr:nth-child(1) { background-color: #363e61; }
table.pasta td { border: 0px solid; padding: 6px; line-height: 1; }
table.pasta td { text-align: right; }
table.pasta th { text-align: center; font-weight: bold; }
table.pasta tr:not(:first-of-type) td:not(:first-of-type) { font-family: monospace; font-weight: bolder; }
table.pasta tr:nth-child(3n+0) { background-color: #112315; }
table.pasta tr:not(:nth-child(3n+0)) td { background-color: #101010; }
table.pasta td:nth-child(4n+5) { background-color: #603302; }
table.pasta tr:nth-child(1) { background-color: #363e61; }
td:empty { visibility: hidden; }
</style>
</li><li><p>pasta: local connections/traffic</p>
<table class="pasta_local" width="70%">
<tr>
<th/>
<th id="perf_pasta_lo_tcp" colspan="__pasta_lo_tcp_cols__">TCP, __pasta_lo_tcp_threads__ at __pasta_lo_tcp_freq__ GHz</th>
<th id="perf_pasta_lo_udp" colspan="__pasta_lo_udp_cols__">UDP, __pasta_lo_udp_threads__ at __pasta_lo_udp_freq__ GHz</th>
</th>
<tr>
<td align="right">MTU:</td>
__pasta_lo_tcp_header__
__pasta_lo_udp_header__
</tr>
__pasta_lo_tcp_LINE__ __pasta_lo_udp_LINE__
</table>
</li><li><p>pasta: connections/traffic via tap</p>
<table class="pasta" width="70%">
<tr>
<th/>
<th id="perf_pasta_tap_tcp" colspan="__pasta_tap_tcp_cols__">TCP, __pasta_tap_tcp_threads__ at __pasta_tap_tcp_freq__ GHz</th>
<th id="perf_pasta_tap_udp" colspan="__pasta_tap_udp_cols__">UDP, __pasta_tap_udp_threads__ at __pasta_tap_udp_freq__ GHz</th>
</tr>
<tr>
<td align="right">MTU:</td>
__pasta_tap_tcp_header__
__pasta_tap_udp_header__
</tr>
__pasta_tap_tcp_LINE__ __pasta_tap_udp_LINE__
</table>
</li></ul>'
PERF_TEMPLATE_JS="');
var perf_links = [
"
PERF_TEMPLATE_POST='];
for (var i = 0; i < perf_links.length; i++) {
var obj = document.getElementById(perf_links[i][0]);
obj.addEventListener("click", function(event) {
var ci_video = document.getElementById("ci");
var top = ci_video.offsetTop - 5;
var seek;
for (var i = 0; i < perf_links.length; i++) {
if (this.id == perf_links[i][0]) {
seek = perf_links[i][1];
}
}
event.preventDefault();
ci_player.dispose();
ci_player = AsciinemaPlayer.create("/builds/latest/web/ci.cast",
ci_video,
{ cols: 240, rows: 51, poster: "npt:999:0", startAt: seek, autoplay: true });
window.scrollTo({ top: top, behavior: "smooth" })
}, false);
}
'
# perf_init() - Process first part of template
perf_init() {
mkdir -p "$(dirname "${PERF_JS}")"
echo "${PERF_TEMPLATE_HTML}" > "${PERF_JS}"
perf_report_sub commit "$(echo ${COMMIT} | sed "s/'/\\\'/g")"
PERF_INIT=1
}
# perf_fill_lines() - Fill multiple "LINE" directives in template, matching rows
perf_fill_lines() {
while true; do
__file_line="$(sed -n '/__.*_LINE__/{=;q}' "${PERF_JS}")"
[ -z "${__file_line}" ] && break
__line_no=0
__done=0
__line_buf="<tr>"
while true; do
__match_first_td=0
for __t in $(sed -n '/__.*_LINE__/{p;q}' "${PERF_JS}"); do
if [ ${__match_first_td} -eq 1 ]; then
__matching_line_no=0
while true; do
__line_part=
__var_name="$(echo $__t | sed -n 's/__\(.*\)__/\1_'"${__matching_line_no}"'/p')"
[ -z "$(eval echo \$${__var_name})" ] && break
__line_part="$(eval echo \$${__var_name})"
__td_check="$(echo "${__line_part}" | sed -n 's/^<td>\([^>]*\)<\/td>.*$/\1/p')"
if [ "${__td_check}" = "${__td_match}" ]; then
__line_part="$(echo "${__line_part}" | sed -n 's/^<td>[^>]*<\/td>\(.*\)$/\1/p')"
break
fi
__matching_line_no=$((__matching_line_no + 1))
done
else
__var_name="$(echo $__t | sed -n 's/__\(.*\)__/\1_'"${__line_no}"'/p')"
[ -z "$(eval echo \$${__var_name})" ] && __done=1 && break
__line_part="$(eval echo \$${__var_name})"
__td_match="$(echo "${__line_part}" | sed -n 's/^<td>\([^>]*\)<\/td>.*$/\1/p')"
fi
__line_buf="${__line_buf}${__line_part}"
__match_first_td=1
done
[ ${__done} -eq 1 ] && break
__line_no=$((__line_no + 1))
__line_buf="${__line_buf}</tr><tr>"
done
__line_buf="${__line_buf}</tr>"
__line_buf="$(printf '%s\n' "${__line_buf}" | sed -e 's/[]\/$*.^[]/\\&/g')"
sed -i "${__file_line}s/.*/${__line_buf}/" "${PERF_JS}"
done
}
# perf_finish() - Add trailing backslashes and process ending templates
perf_finish() {
PERF_INIT=0
perf_fill_lines
sed -i 's/^.*$/&\\/g' "${PERF_JS}"
echo "${PERF_TEMPLATE_JS}" >> "${PERF_JS}"
echo "${PERF_TEMPLATE_POST}" >> "${PERF_JS}"
}
# perf_report_sub() - Apply simple substitutions in template
perf_report_sub() {
__et="$(printf '%s\n' "${1}" | sed -e 's/[\/&]/\\&/g')"
__es="$(printf '%s\n' "${2}" | sed -e 's/[]\/$*.^[]/\\&/g')"
sed -i 's/__'"${__et}"'__/'"${__es}"'/g' "${PERF_JS}"
}
# perf_report_append_js() - Append generic string to current template buffer
perf_report_append_js() {
PERF_TEMPLATE_JS="${PERF_TEMPLATE_JS}${@}"
}
# perf_report() - Start of single test report
perf_report() {
__mode="${1}"
__proto="${2}"
__threads="${3}"
__freq="${4}"
REPORT_IN="${__mode}_${__proto}"
[ ${__threads} -eq 1 ] && __threads="one thread" || __threads="${__threads} threads"
perf_report_sub "${__mode}_${__proto}_threads" "${__threads}"
perf_report_sub "${__mode}_${__proto}_freq" "${__freq}"
perf_report_append_js "[ 'perf_${__mode}_${__proto}', $(video_time_now) ],"
}
# perf_th() - Table header for a set of tests
perf_th() {
[ ${PERF_INIT} -eq 0 ] && return
shift
__th_buf=
__cols_count=0
for __arg; do
__th_buf="${__th_buf}<td>${__arg}</td>"
__cols_count=$((__cols_count + 1))
done
perf_report_sub "${REPORT_IN}_header" "${__th_buf}"
perf_report_sub "${REPORT_IN}_cols" ${__cols_count}
}
# perf_tr() - Main table row
perf_tr() {
[ ${PERF_INIT} -eq 0 ] && return
__line_no=0
shift
while true; do
[ -z "$(eval echo \$${REPORT_IN}_LINE_${__line_no})" ] && break
__line_no=$((__line_no + 1))
done
eval ${REPORT_IN}_LINE_${__line_no}="\"<td>${@}</td>\""
}
# perf_td() - Single cell with test result
perf_td() {
[ ${PERF_INIT} -eq 0 ] && return
__rewind="${1}"
shift
__line_no=0
while true; do
[ -z "$(eval echo \$${REPORT_IN}_LINE_${__line_no})" ] && break
__line_no=$((__line_no + 1))
done
__line_no=$((__line_no - 1))
[ -z "${1}" ] && __id=0 || __id="perf_${PERF_LINK_COUNT}"
eval ${REPORT_IN}_LINE_${__line_no}=\""\${${REPORT_IN}_LINE_${__line_no}}<td id=\"${__id}\">${1}</td>"\"
[ -z "${1}" ] && return
perf_report_append_js "[ '${__id}', $(($(video_time_now) - ${__rewind})) ],"
PERF_LINK_COUNT=$((PERF_LINK_COUNT + 1))
}
# perf_te() - End of a table, currently unused
pert_te() {
:
}
|