5
5
import concurrent
6
6
import glob
7
7
import os
8
- import shutil
9
8
from pathlib import Path
10
9
11
10
import pytest
@@ -45,7 +44,7 @@ def prepare_microvm_for_test(microvm):
45
44
check_output ("echo 3 > /proc/sys/vm/drop_caches" )
46
45
47
46
48
- def run_fio (microvm , mode , block_size , fio_engine = "libaio" ):
47
+ def run_fio (microvm , mode , block_size , test_output_dir , fio_engine = "libaio" ):
49
48
"""Run a fio test in the specified mode with block size bs."""
50
49
cmd = (
51
50
CmdBuilder ("fio" )
@@ -71,16 +70,10 @@ def run_fio(microvm, mode, block_size, fio_engine="libaio"):
71
70
.with_arg (f"--write_bw_log={ mode } " )
72
71
.with_arg (f"--write_lat_log={ mode } " )
73
72
.with_arg ("--log_avg_msec=1000" )
73
+ .with_arg ("--output-format=json+" )
74
74
.build ()
75
75
)
76
76
77
- logs_path = Path (microvm .jailer .chroot_base_with_id ()) / "fio_output"
78
-
79
- if logs_path .is_dir ():
80
- shutil .rmtree (logs_path )
81
-
82
- logs_path .mkdir ()
83
-
84
77
prepare_microvm_for_test (microvm )
85
78
86
79
# Start the CPU load monitor.
@@ -93,21 +86,31 @@ def run_fio(microvm, mode, block_size, fio_engine="libaio"):
93
86
)
94
87
95
88
# Print the fio command in the log and run it
96
- rc , _ , stderr = microvm .ssh .run (f"cd /tmp; { cmd } " )
89
+ rc , stdout , stderr = microvm .ssh .run (f"cd /tmp; { cmd } " )
97
90
assert rc == 0 , stderr
98
91
assert stderr == ""
99
92
100
- microvm .ssh .scp_get ("/tmp/*.log" , logs_path )
93
+ fio_json_path = Path (test_output_dir / "fio.json" )
94
+ with open (fio_json_path , "w" , encoding = "utf-8" ) as f :
95
+ f .write (stdout )
96
+
97
+ microvm .ssh .scp_get ("/tmp/*.log" , test_output_dir )
101
98
microvm .ssh .check_output ("rm /tmp/*.log" )
102
99
103
- return logs_path , cpu_load_future .result ()
100
+ return cpu_load_future .result ()
104
101
105
102
106
- def process_fio_log_files (logs_glob ):
107
- """Parses all fio log files matching the given glob and yields tuples of same-timestamp read and write metrics"""
103
+ def process_fio_log_files (root_dir , logs_glob ):
104
+ """
105
+ Parses all fio log files in the root_dir matching the given glob and
106
+ yields tuples of same-timestamp read and write metrics
107
+ """
108
+ # We specify `root_dir` for `glob.glob` because otherwise it will
109
+ # struggle with directory with names like:
110
+ # test_block_performance[vmlinux-5.10.233-Sync-bs4096-randread-1vcpu]
108
111
data = [
109
- Path (pathname ).read_text ("UTF-8" ).splitlines ()
110
- for pathname in glob .glob (logs_glob )
112
+ Path (root_dir / pathname ).read_text ("UTF-8" ).splitlines ()
113
+ for pathname in glob .glob (logs_glob , root_dir = root_dir )
111
114
]
112
115
113
116
assert data , "no log files found!"
@@ -134,13 +137,13 @@ def process_fio_log_files(logs_glob):
134
137
135
138
def emit_fio_metrics (logs_dir , metrics ):
136
139
"""Parses the fio logs in `{logs_dir}/*_[clat|bw].*.log and emits their contents as CloudWatch metrics"""
137
- for bw_read , bw_write in process_fio_log_files (f" { logs_dir } / *_bw.*.log" ):
140
+ for bw_read , bw_write in process_fio_log_files (logs_dir , " *_bw.*.log" ):
138
141
if bw_read :
139
142
metrics .put_metric ("bw_read" , sum (bw_read ), "Kilobytes/Second" )
140
143
if bw_write :
141
144
metrics .put_metric ("bw_write" , sum (bw_write ), "Kilobytes/Second" )
142
145
143
- for lat_read , lat_write in process_fio_log_files (f" { logs_dir } / *_clat.*.log" ):
146
+ for lat_read , lat_write in process_fio_log_files (logs_dir , " *_clat.*.log" ):
144
147
# latency values in fio logs are in nanoseconds, but cloudwatch only supports
145
148
# microseconds as the more granular unit, so need to divide by 1000.
146
149
for value in lat_read :
@@ -164,6 +167,7 @@ def test_block_performance(
164
167
fio_engine ,
165
168
io_engine ,
166
169
metrics ,
170
+ results_dir ,
167
171
):
168
172
"""
169
173
Execute block device emulation benchmarking scenarios.
@@ -192,9 +196,9 @@ def test_block_performance(
192
196
193
197
vm .pin_threads (0 )
194
198
195
- logs_dir , cpu_util = run_fio (vm , fio_mode , fio_block_size , fio_engine )
199
+ cpu_util = run_fio (vm , fio_mode , fio_block_size , results_dir , fio_engine )
196
200
197
- emit_fio_metrics (logs_dir , metrics )
201
+ emit_fio_metrics (results_dir , metrics )
198
202
199
203
for thread_name , values in cpu_util .items ():
200
204
for value in values :
@@ -213,6 +217,7 @@ def test_block_vhost_user_performance(
213
217
fio_mode ,
214
218
fio_block_size ,
215
219
metrics ,
220
+ results_dir ,
216
221
):
217
222
"""
218
223
Execute block device emulation benchmarking scenarios.
@@ -242,9 +247,9 @@ def test_block_vhost_user_performance(
242
247
next_cpu = vm .pin_threads (0 )
243
248
vm .disks_vhost_user ["scratch" ].pin (next_cpu )
244
249
245
- logs_dir , cpu_util = run_fio (vm , fio_mode , fio_block_size )
250
+ cpu_util = run_fio (vm , fio_mode , fio_block_size , results_dir )
246
251
247
- emit_fio_metrics (logs_dir , metrics )
252
+ emit_fio_metrics (results_dir , metrics )
248
253
249
254
for thread_name , values in cpu_util .items ():
250
255
for value in values :
0 commit comments