Skip to content

Commit 5f3b54f

Browse files
authored
Merge pull request #204 from kzys/signal-benchmark
Remove signal handling channels correctly
2 parents 84c518f + f8cf437 commit 5f3b54f

File tree

2 files changed

+141
-2
lines changed

2 files changed

+141
-2
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+
}

machine.go

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -953,13 +953,16 @@ func (m *Machine) setupSignals() {
953953
signal.Notify(sigchan, signals...)
954954

955955
go func() {
956+
ForLoop:
956957
for {
957958
select {
958959
case sig := <-sigchan:
959-
m.logger.Printf("Caught signal %s", sig)
960+
m.logger.Debugf("Caught signal %s", sig)
961+
// Some signals kill the process, some of them are not.
960962
m.cmd.Process.Signal(sig)
961963
case <-m.exitCh:
962-
break
964+
// And if a signal kills the process, we can stop this for loop and remove sigchan.
965+
break ForLoop
963966
}
964967
}
965968

0 commit comments

Comments
 (0)