Skip to content

Commit 92c80d0

Browse files
committed
feat: add jailer performance tests
The test measures p50 and p90 of jailer startup time. It is parametrized by the number of jailers starting up and the number of bind mount points present in the system. Signed-off-by: Egor Lazarchuk <[email protected]>
1 parent f87a258 commit 92c80d0

File tree

1 file changed

+84
-0
lines changed

1 file changed

+84
-0
lines changed
Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
# Copyright 2025 Amazon.com, Inc. or its affiliates. All Rights Reserved.
2+
# SPDX-License-Identifier: Apache-2.0
3+
"""Performance benchmark for the jailer."""
4+
5+
import os
6+
import shutil
7+
import subprocess
8+
9+
import pytest
10+
11+
from framework import utils
12+
from framework.jailer import DEFAULT_CHROOT_PATH, JailerContext
13+
from framework.properties import global_props
14+
15+
16+
@pytest.mark.nonci
17+
@pytest.mark.parametrize("jailers", [1, 100, 300, 500])
18+
@pytest.mark.parametrize("mounts", [0, 100, 300, 500])
19+
def test_jailer_startup(
20+
jailer_time_bin, tmp_path, microvm_factory, jailers, mounts, metrics
21+
):
22+
"""
23+
Test the overhead of jailer startup without and with bind mounts
24+
"""
25+
26+
jailer_binary = microvm_factory.jailer_binary_path
27+
28+
# Create bind mount points. The exact location of them
29+
# does not matter, they just need to exist.
30+
mounts_paths = tmp_path / "mounts"
31+
os.makedirs(mounts_paths)
32+
for m in range(mounts):
33+
mount_path = f"{mounts_paths}/mount{m}"
34+
os.makedirs(mount_path)
35+
utils.check_output(f"mount --bind {mount_path} {mount_path}")
36+
37+
metrics.set_dimensions(
38+
{
39+
"instance": global_props.instance,
40+
"cpu_model": global_props.cpu_model,
41+
"performance_test": "test_jailer_startup",
42+
"jailers": str(jailers),
43+
"mounts": str(mounts),
44+
}
45+
)
46+
47+
# Testing 1 jailer will give 1 data point which is not enough,
48+
# so do 100 runs in this case.
49+
if jailers == 1:
50+
iterations = 100
51+
else:
52+
iterations = 1
53+
54+
for i in range(iterations):
55+
processes = []
56+
for j in range(jailers):
57+
jailer = JailerContext(
58+
jailer_id=f"fakefc{i}{j}",
59+
exec_file=jailer_time_bin,
60+
# Don't deamonize to get the stdout
61+
daemonize=False,
62+
)
63+
jailer.setup()
64+
65+
cmd = [str(jailer_binary), *jailer.construct_param_list()]
66+
processes.append(
67+
subprocess.Popen(
68+
cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=False
69+
)
70+
)
71+
72+
for p in processes:
73+
stdout = p.communicate()[0]
74+
end_time, start_time = stdout.split()
75+
metrics.put_metric(
76+
"startup",
77+
int(end_time) - int(start_time),
78+
unit="Microseconds",
79+
)
80+
81+
# Cleanup mounts and jailer dirs
82+
for d in os.listdir(mounts_paths):
83+
utils.check_output(f"umount {mounts_paths}/{d}")
84+
shutil.rmtree(DEFAULT_CHROOT_PATH)

0 commit comments

Comments
 (0)