Skip to content

Commit c3bc513

Browse files
committed
Reproduce #198
Since the cause is a process-level resource leak, running these benchmarks in a same process (e.g. go test -bench=BenchmarkForwardSignals) doesn't show the difference. Signed-off-by: Kazuyoshi Kato <[email protected]>
1 parent a3f9b2f commit c3bc513

File tree

1 file changed

+136
-0
lines changed

1 file changed

+136
-0
lines changed

benchmark_test.go

Lines changed: 136 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,136 @@
1+
package firecracker
2+
3+
import (
4+
"bufio"
5+
"context"
6+
"io/ioutil"
7+
"os"
8+
"path/filepath"
9+
"strings"
10+
"sync"
11+
"testing"
12+
13+
"github.com/sirupsen/logrus"
14+
15+
models "github.com/firecracker-microvm/firecracker-go-sdk/client/models"
16+
)
17+
18+
const numberOfVMs = 200
19+
20+
func createMachine(ctx context.Context, name string, forwardSignals []os.Signal) (*Machine, func(), error) {
21+
dir, err := ioutil.TempDir("", name)
22+
if err != nil {
23+
return nil, nil, err
24+
}
25+
cleanup := func() {
26+
os.RemoveAll(dir)
27+
}
28+
29+
socketPath := filepath.Join(dir, "api.sock")
30+
vmlinuxPath := filepath.Join(testDataPath, "./vmlinux")
31+
logFifo := filepath.Join(dir, "log.fifo")
32+
metrics := filepath.Join(dir, "metrics.fifo")
33+
34+
config := Config{
35+
SocketPath: socketPath,
36+
KernelImagePath: vmlinuxPath,
37+
LogFifo: logFifo,
38+
MetricsFifo: metrics,
39+
LogLevel: "Info",
40+
MachineCfg: models.MachineConfiguration{
41+
VcpuCount: Int64(1),
42+
CPUTemplate: models.CPUTemplate(models.CPUTemplateT2),
43+
MemSizeMib: Int64(256),
44+
HtEnabled: Bool(false),
45+
},
46+
Drives: []models.Drive{
47+
{
48+
DriveID: String("root"),
49+
IsRootDevice: Bool(true),
50+
IsReadOnly: Bool(true),
51+
PathOnHost: String(testRootfs),
52+
},
53+
},
54+
ForwardSignals: forwardSignals,
55+
}
56+
57+
cmd := VMCommandBuilder{}.
58+
WithSocketPath(socketPath).
59+
WithBin(getFirecrackerBinaryPath()).
60+
Build(ctx)
61+
62+
log := logrus.New()
63+
log.SetLevel(logrus.FatalLevel)
64+
machine, err := NewMachine(ctx, config, WithProcessRunner(cmd), WithLogger(logrus.NewEntry(log)))
65+
if err != nil {
66+
return nil, cleanup, err
67+
}
68+
69+
return machine, cleanup, nil
70+
}
71+
72+
func startAndWaitVM(ctx context.Context, m *Machine) error {
73+
err := m.Start(ctx)
74+
if err != nil {
75+
return err
76+
}
77+
78+
file, err := os.Open(m.LogFile())
79+
if err != nil {
80+
return err
81+
}
82+
83+
scanner := bufio.NewScanner(file)
84+
for scanner.Scan() {
85+
line := scanner.Text()
86+
if strings.Contains(line, "Guest-boot-time") {
87+
break
88+
}
89+
}
90+
err = m.StopVMM()
91+
if err != nil {
92+
return err
93+
}
94+
95+
err = m.Wait(ctx)
96+
if err != nil {
97+
return err
98+
}
99+
100+
return nil
101+
}
102+
103+
func benchmarkForwardSignals(b *testing.B, forwardSignals []os.Signal) {
104+
ctx := context.Background()
105+
106+
b.Logf("%s: %d", b.Name(), b.N)
107+
108+
for i := 0; i < b.N; i++ {
109+
var wg sync.WaitGroup
110+
for j := 0; j < numberOfVMs; j++ {
111+
wg.Add(1)
112+
go func() {
113+
defer wg.Done()
114+
115+
machine, cleanup, err := createMachine(ctx, b.Name(), forwardSignals)
116+
if err != nil {
117+
b.Fatalf("failed to create a VM: %s", err)
118+
}
119+
defer cleanup()
120+
121+
err = startAndWaitVM(ctx, machine)
122+
if err != nil && !strings.Contains(err.Error(), "signal: terminated") {
123+
b.Fatalf("failed to start the VM: %s", err)
124+
}
125+
}()
126+
}
127+
wg.Wait()
128+
}
129+
}
130+
func BenchmarkForwardSignalsDefault(t *testing.B) {
131+
benchmarkForwardSignals(t, nil)
132+
}
133+
134+
func BenchmarkForwardSignalsDisable(t *testing.B) {
135+
benchmarkForwardSignals(t, []os.Signal{})
136+
}

0 commit comments

Comments
 (0)