From 7ad3bb96f4d07bdd8b20b561257a84c7f18c3829 Mon Sep 17 00:00:00 2001 From: Paul Buetow Date: Sun, 8 Mar 2026 11:47:00 +0200 Subject: benchutil: replace event serialization panics with errors --- internal/bench_components_test.go | 135 +++++++++++++++++++++++------ internal/bench_pipeline_test.go | 5 +- internal/benchutil/eventgen.go | 166 +++++++++++++++++++++++------------- internal/benchutil/eventgen_test.go | 70 ++++++++++----- internal/benchutil/eventmix.go | 37 +++++--- 5 files changed, 295 insertions(+), 118 deletions(-) (limited to 'internal') diff --git a/internal/bench_components_test.go b/internal/bench_components_test.go index 54c6f2e..715aabc 100644 --- a/internal/bench_components_test.go +++ b/internal/bench_components_test.go @@ -22,49 +22,73 @@ type recyclable interface { func BenchmarkDeserializeOpenEvent(b *testing.B) { gen := benchutil.NewEventGenerator() - _, raw := gen.EnterOpenEvent(1, componentBenchPID, componentBenchTID) + _, raw, err := gen.EnterOpenEvent(1, componentBenchPID, componentBenchTID) + if err != nil { + b.Fatal(err) + } benchmarkDeserialize(b, raw, types.NewOpenEvent) } func BenchmarkDeserializeFdEvent(b *testing.B) { gen := benchutil.NewEventGenerator() - _, raw := gen.EnterFdEvent(1, componentBenchPID, componentBenchTID, 12, types.SYS_ENTER_READ) + _, raw, err := gen.EnterFdEvent(1, componentBenchPID, componentBenchTID, 12, types.SYS_ENTER_READ) + if err != nil { + b.Fatal(err) + } benchmarkDeserialize(b, raw, types.NewFdEvent) } func BenchmarkDeserializeNullEvent(b *testing.B) { gen := benchutil.NewEventGenerator() - _, raw := gen.EnterNullEvent(1, componentBenchPID, componentBenchTID, types.SYS_ENTER_SYNC) + _, raw, err := gen.EnterNullEvent(1, componentBenchPID, componentBenchTID, types.SYS_ENTER_SYNC) + if err != nil { + b.Fatal(err) + } benchmarkDeserialize(b, raw, types.NewNullEvent) } func BenchmarkDeserializeRetEvent(b *testing.B) { gen := benchutil.NewEventGenerator() - _, raw := gen.ExitRetEvent(1, componentBenchPID, componentBenchTID, types.SYS_EXIT_READ, 64) + _, raw, err := gen.ExitRetEvent(1, componentBenchPID, componentBenchTID, types.SYS_EXIT_READ, 64) + if err != nil { + b.Fatal(err) + } benchmarkDeserialize(b, raw, types.NewRetEvent) } func BenchmarkDeserializePathEvent(b *testing.B) { gen := benchutil.NewEventGenerator() - _, raw := gen.EnterPathEvent(1, componentBenchPID, componentBenchTID, "/tmp/p", types.SYS_ENTER_MKDIR) + _, raw, err := gen.EnterPathEvent(1, componentBenchPID, componentBenchTID, "/tmp/p", types.SYS_ENTER_MKDIR) + if err != nil { + b.Fatal(err) + } benchmarkDeserialize(b, raw, types.NewPathEvent) } func BenchmarkDeserializeNameEvent(b *testing.B) { gen := benchutil.NewEventGenerator() - _, raw := gen.EnterNameEvent(1, componentBenchPID, componentBenchTID, "/tmp/a", "/tmp/b", types.SYS_ENTER_RENAME) + _, raw, err := gen.EnterNameEvent(1, componentBenchPID, componentBenchTID, "/tmp/a", "/tmp/b", types.SYS_ENTER_RENAME) + if err != nil { + b.Fatal(err) + } benchmarkDeserialize(b, raw, types.NewNameEvent) } func BenchmarkDeserializeFcntlEvent(b *testing.B) { gen := benchutil.NewEventGenerator() - _, raw := gen.EnterFcntlEvent(1, componentBenchPID, componentBenchTID, 33, syscall.F_SETFL, syscall.O_NONBLOCK) + _, raw, err := gen.EnterFcntlEvent(1, componentBenchPID, componentBenchTID, 33, syscall.F_SETFL, syscall.O_NONBLOCK) + if err != nil { + b.Fatal(err) + } benchmarkDeserialize(b, raw, types.NewFcntlEvent) } func BenchmarkDeserializeDup3Event(b *testing.B) { gen := benchutil.NewEventGenerator() - _, raw := gen.EnterDup3Event(1, componentBenchPID, componentBenchTID, 8, syscall.O_CLOEXEC) + _, raw, err := gen.EnterDup3Event(1, componentBenchPID, componentBenchTID, 8, syscall.O_CLOEXEC) + if err != nil { + b.Fatal(err) + } benchmarkDeserialize(b, raw, types.NewDup3Event) } @@ -96,7 +120,10 @@ func BenchmarkTracepointEntered(b *testing.B) { b.ReportAllocs() gen := benchutil.NewEventGenerator() - _, raw := gen.EnterOpenEvent(1, componentBenchPID, componentBenchTID) + _, raw, err := gen.EnterOpenEvent(1, componentBenchPID, componentBenchTID) + if err != nil { + b.Fatal(err) + } el := newComponentBenchEventLoop(b, componentBenchTID) b.ResetTimer() @@ -116,8 +143,14 @@ func BenchmarkTracepointExited(b *testing.B) { b.ReportAllocs() gen := benchutil.NewEventGenerator() - _, enterRaw := gen.EnterNullEvent(1, componentBenchPID, componentBenchTID, types.SYS_ENTER_SYNC) - _, exitRaw := gen.ExitNullEvent(2, componentBenchPID, componentBenchTID, types.SYS_EXIT_SYNC) + _, enterRaw, err := gen.EnterNullEvent(1, componentBenchPID, componentBenchTID, types.SYS_ENTER_SYNC) + if err != nil { + b.Fatal(err) + } + _, exitRaw, err := gen.ExitNullEvent(2, componentBenchPID, componentBenchTID, types.SYS_EXIT_SYNC) + if err != nil { + b.Fatal(err) + } el := newComponentBenchEventLoop(b, componentBenchTID) out := make(chan *event.Pair, 1) @@ -135,8 +168,14 @@ func BenchmarkHandleOpenExit(b *testing.B) { b.ReportAllocs() gen := benchutil.NewEventGenerator() - enterTemplate, _ := gen.EnterOpenEvent(1, componentBenchPID, componentBenchTID) - exitTemplate, _ := gen.ExitOpenEvent(2, componentBenchPID, componentBenchTID) + enterTemplate, _, err := gen.EnterOpenEvent(1, componentBenchPID, componentBenchTID) + if err != nil { + b.Fatal(err) + } + exitTemplate, _, err := gen.ExitOpenEvent(2, componentBenchPID, componentBenchTID) + if err != nil { + b.Fatal(err) + } el := newComponentBenchEventLoop(b, componentBenchTID) b.ResetTimer() @@ -158,8 +197,14 @@ func BenchmarkHandleFdExit(b *testing.B) { b.ReportAllocs() gen := benchutil.NewEventGenerator() - enterTemplate, _ := gen.EnterFdEvent(1, componentBenchPID, componentBenchTID, 99, types.SYS_ENTER_READ) - exitTemplate, _ := gen.ExitRetEvent(2, componentBenchPID, componentBenchTID, types.SYS_EXIT_READ, 128) + enterTemplate, _, err := gen.EnterFdEvent(1, componentBenchPID, componentBenchTID, 99, types.SYS_ENTER_READ) + if err != nil { + b.Fatal(err) + } + exitTemplate, _, err := gen.ExitRetEvent(2, componentBenchPID, componentBenchTID, types.SYS_EXIT_READ, 128) + if err != nil { + b.Fatal(err) + } el := newComponentBenchEventLoop(b, componentBenchTID) el.fdState().set(99, file.NewFd(99, "/tmp/fd", syscall.O_RDONLY)) @@ -182,8 +227,14 @@ func BenchmarkHandlePathExit(b *testing.B) { b.ReportAllocs() gen := benchutil.NewEventGenerator() - enterTemplate, _ := gen.EnterPathEvent(1, componentBenchPID, componentBenchTID, "/tmp/path", types.SYS_ENTER_MKDIR) - exitTemplate, _ := gen.ExitRetEvent(2, componentBenchPID, componentBenchTID, types.SYS_EXIT_MKDIR, 0) + enterTemplate, _, err := gen.EnterPathEvent(1, componentBenchPID, componentBenchTID, "/tmp/path", types.SYS_ENTER_MKDIR) + if err != nil { + b.Fatal(err) + } + exitTemplate, _, err := gen.ExitRetEvent(2, componentBenchPID, componentBenchTID, types.SYS_EXIT_MKDIR, 0) + if err != nil { + b.Fatal(err) + } el := newComponentBenchEventLoop(b, componentBenchTID) b.ResetTimer() @@ -205,8 +256,14 @@ func BenchmarkHandleNameExit(b *testing.B) { b.ReportAllocs() gen := benchutil.NewEventGenerator() - enterTemplate, _ := gen.EnterNameEvent(1, componentBenchPID, componentBenchTID, "/tmp/a", "/tmp/b", types.SYS_ENTER_RENAME) - exitTemplate, _ := gen.ExitRetEvent(2, componentBenchPID, componentBenchTID, types.SYS_EXIT_RENAME, 0) + enterTemplate, _, err := gen.EnterNameEvent(1, componentBenchPID, componentBenchTID, "/tmp/a", "/tmp/b", types.SYS_ENTER_RENAME) + if err != nil { + b.Fatal(err) + } + exitTemplate, _, err := gen.ExitRetEvent(2, componentBenchPID, componentBenchTID, types.SYS_EXIT_RENAME, 0) + if err != nil { + b.Fatal(err) + } el := newComponentBenchEventLoop(b, componentBenchTID) b.ResetTimer() @@ -228,8 +285,14 @@ func BenchmarkHandleNullExit(b *testing.B) { b.ReportAllocs() gen := benchutil.NewEventGenerator() - enterTemplate, _ := gen.EnterNullEvent(1, componentBenchPID, componentBenchTID, types.SYS_ENTER_SYNC) - exitTemplate, _ := gen.ExitNullEvent(2, componentBenchPID, componentBenchTID, types.SYS_EXIT_SYNC) + enterTemplate, _, err := gen.EnterNullEvent(1, componentBenchPID, componentBenchTID, types.SYS_ENTER_SYNC) + if err != nil { + b.Fatal(err) + } + exitTemplate, _, err := gen.ExitNullEvent(2, componentBenchPID, componentBenchTID, types.SYS_EXIT_SYNC) + if err != nil { + b.Fatal(err) + } el := newComponentBenchEventLoop(b, componentBenchTID) b.ResetTimer() @@ -251,8 +314,14 @@ func BenchmarkHandleFcntlExit(b *testing.B) { b.ReportAllocs() gen := benchutil.NewEventGenerator() - enterTemplate, _ := gen.EnterFcntlEvent(1, componentBenchPID, componentBenchTID, 7, syscall.F_SETFL, syscall.O_NONBLOCK) - exitTemplate, _ := gen.ExitRetEvent(2, componentBenchPID, componentBenchTID, types.SYS_EXIT_FCNTL, 0) + enterTemplate, _, err := gen.EnterFcntlEvent(1, componentBenchPID, componentBenchTID, 7, syscall.F_SETFL, syscall.O_NONBLOCK) + if err != nil { + b.Fatal(err) + } + exitTemplate, _, err := gen.ExitRetEvent(2, componentBenchPID, componentBenchTID, types.SYS_EXIT_FCNTL, 0) + if err != nil { + b.Fatal(err) + } el := newComponentBenchEventLoop(b, componentBenchTID) el.fdState().set(7, file.NewFd(7, "/tmp/fcntl", syscall.O_RDONLY)) @@ -275,8 +344,14 @@ func BenchmarkHandleDup3Exit(b *testing.B) { b.ReportAllocs() gen := benchutil.NewEventGenerator() - enterTemplate, _ := gen.EnterDup3Event(1, componentBenchPID, componentBenchTID, 9, syscall.O_CLOEXEC) - exitTemplate, _ := gen.ExitRetEvent(2, componentBenchPID, componentBenchTID, types.SYS_EXIT_DUP3, 10) + enterTemplate, _, err := gen.EnterDup3Event(1, componentBenchPID, componentBenchTID, 9, syscall.O_CLOEXEC) + if err != nil { + b.Fatal(err) + } + exitTemplate, _, err := gen.ExitRetEvent(2, componentBenchPID, componentBenchTID, types.SYS_EXIT_DUP3, 10) + if err != nil { + b.Fatal(err) + } el := newComponentBenchEventLoop(b, componentBenchTID) el.fdState().set(9, file.NewFd(9, "/tmp/dup3", syscall.O_RDONLY)) @@ -328,8 +403,14 @@ func BenchmarkEventPoolGetPut(b *testing.B) { b.ReportAllocs() gen := benchutil.NewEventGenerator() - enterTemplate, _ := gen.EnterNullEvent(1, componentBenchPID, componentBenchTID, types.SYS_ENTER_SYNC) - exitTemplate, _ := gen.ExitNullEvent(2, componentBenchPID, componentBenchTID, types.SYS_EXIT_SYNC) + enterTemplate, _, err := gen.EnterNullEvent(1, componentBenchPID, componentBenchTID, types.SYS_ENTER_SYNC) + if err != nil { + b.Fatal(err) + } + exitTemplate, _, err := gen.ExitNullEvent(2, componentBenchPID, componentBenchTID, types.SYS_EXIT_SYNC) + if err != nil { + b.Fatal(err) + } b.ResetTimer() for i := 0; i < b.N; i++ { diff --git a/internal/bench_pipeline_test.go b/internal/bench_pipeline_test.go index aa48302..80001f3 100644 --- a/internal/bench_pipeline_test.go +++ b/internal/bench_pipeline_test.go @@ -53,7 +53,10 @@ func benchmarkPipelineMix(b *testing.B, mix benchutil.EventMix, events, numThrea b.ReportAllocs() gen := benchutil.NewEventGenerator() - stream := mix.GenerateStream(gen, events, numThreads) + stream, err := mix.GenerateStream(gen, events, numThreads) + if err != nil { + b.Fatalf("generate stream: %v", err) + } if len(stream) == 0 { b.Fatal("generated empty benchmark stream") } diff --git a/internal/benchutil/eventgen.go b/internal/benchutil/eventgen.go index 3f8b345..0c0ec9c 100644 --- a/internal/benchutil/eventgen.go +++ b/internal/benchutil/eventgen.go @@ -1,7 +1,6 @@ package benchutil import ( - "fmt" "syscall" "ior/internal/generate" @@ -24,7 +23,7 @@ func NewEventGenerator() EventGenerator { return EventGenerator{PairDelta: defaultPairDelta} } -func (g EventGenerator) EnterOpenEvent(time uint64, pid, tid uint32) (types.OpenEvent, []byte) { +func (g EventGenerator) EnterOpenEvent(time uint64, pid, tid uint32) (types.OpenEvent, []byte, error) { ev := types.OpenEvent{ EventType: types.ENTER_OPEN_EVENT, TraceId: types.SYS_ENTER_OPENAT, @@ -37,10 +36,11 @@ func (g EventGenerator) EnterOpenEvent(time uint64, pid, tid uint32) (types.Open } copy(ev.Filename[:], defaultOpenName) copy(ev.Comm[:], defaultOpenComm) - return ev, mustBytes(&ev) + raw, err := eventBytes(&ev) + return ev, raw, err } -func (g EventGenerator) ExitOpenEvent(time uint64, pid, tid uint32) (types.RetEvent, []byte) { +func (g EventGenerator) ExitOpenEvent(time uint64, pid, tid uint32) (types.RetEvent, []byte, error) { ev := types.RetEvent{ EventType: types.EXIT_OPEN_EVENT, TraceId: types.SYS_EXIT_OPENAT, @@ -49,10 +49,11 @@ func (g EventGenerator) ExitOpenEvent(time uint64, pid, tid uint32) (types.RetEv Pid: pid, Tid: tid, } - return ev, mustBytes(&ev) + raw, err := eventBytes(&ev) + return ev, raw, err } -func (g EventGenerator) EnterFdEvent(time uint64, pid, tid uint32, fd int32, traceID types.TraceId) (types.FdEvent, []byte) { +func (g EventGenerator) EnterFdEvent(time uint64, pid, tid uint32, fd int32, traceID types.TraceId) (types.FdEvent, []byte, error) { ev := types.FdEvent{ EventType: types.ENTER_FD_EVENT, TraceId: traceID, @@ -61,10 +62,11 @@ func (g EventGenerator) EnterFdEvent(time uint64, pid, tid uint32, fd int32, tra Tid: tid, Fd: fd, } - return ev, mustBytes(&ev) + raw, err := eventBytes(&ev) + return ev, raw, err } -func (g EventGenerator) ExitFdEvent(time uint64, pid, tid uint32, fd int32, traceID types.TraceId) (types.FdEvent, []byte) { +func (g EventGenerator) ExitFdEvent(time uint64, pid, tid uint32, fd int32, traceID types.TraceId) (types.FdEvent, []byte, error) { ev := types.FdEvent{ EventType: types.EXIT_FD_EVENT, TraceId: traceID, @@ -73,10 +75,11 @@ func (g EventGenerator) ExitFdEvent(time uint64, pid, tid uint32, fd int32, trac Tid: tid, Fd: fd, } - return ev, mustBytes(&ev) + raw, err := eventBytes(&ev) + return ev, raw, err } -func (g EventGenerator) EnterNullEvent(time uint64, pid, tid uint32, traceID types.TraceId) (types.NullEvent, []byte) { +func (g EventGenerator) EnterNullEvent(time uint64, pid, tid uint32, traceID types.TraceId) (types.NullEvent, []byte, error) { ev := types.NullEvent{ EventType: types.ENTER_NULL_EVENT, TraceId: traceID, @@ -84,10 +87,11 @@ func (g EventGenerator) EnterNullEvent(time uint64, pid, tid uint32, traceID typ Pid: pid, Tid: tid, } - return ev, mustBytes(&ev) + raw, err := eventBytes(&ev) + return ev, raw, err } -func (g EventGenerator) ExitNullEvent(time uint64, pid, tid uint32, traceID types.TraceId) (types.NullEvent, []byte) { +func (g EventGenerator) ExitNullEvent(time uint64, pid, tid uint32, traceID types.TraceId) (types.NullEvent, []byte, error) { ev := types.NullEvent{ EventType: types.EXIT_NULL_EVENT, TraceId: traceID, @@ -95,10 +99,11 @@ func (g EventGenerator) ExitNullEvent(time uint64, pid, tid uint32, traceID type Pid: pid, Tid: tid, } - return ev, mustBytes(&ev) + raw, err := eventBytes(&ev) + return ev, raw, err } -func (g EventGenerator) ExitRetEvent(time uint64, pid, tid uint32, traceID types.TraceId, ret int64) (types.RetEvent, []byte) { +func (g EventGenerator) ExitRetEvent(time uint64, pid, tid uint32, traceID types.TraceId, ret int64) (types.RetEvent, []byte, error) { ev := types.RetEvent{ EventType: types.EXIT_RET_EVENT, TraceId: traceID, @@ -108,10 +113,11 @@ func (g EventGenerator) ExitRetEvent(time uint64, pid, tid uint32, traceID types Tid: tid, RetType: retType(traceID), } - return ev, mustBytes(&ev) + raw, err := eventBytes(&ev) + return ev, raw, err } -func (g EventGenerator) EnterPathEvent(time uint64, pid, tid uint32, pathname string, traceID types.TraceId) (types.PathEvent, []byte) { +func (g EventGenerator) EnterPathEvent(time uint64, pid, tid uint32, pathname string, traceID types.TraceId) (types.PathEvent, []byte, error) { ev := types.PathEvent{ EventType: types.ENTER_PATH_EVENT, TraceId: traceID, @@ -121,10 +127,11 @@ func (g EventGenerator) EnterPathEvent(time uint64, pid, tid uint32, pathname st Pathname: [types.MAX_FILENAME_LENGTH]byte{}, } copy(ev.Pathname[:], pathname) - return ev, mustBytes(&ev) + raw, err := eventBytes(&ev) + return ev, raw, err } -func (g EventGenerator) EnterNameEvent(time uint64, pid, tid uint32, oldname, newname string, traceID types.TraceId) (types.NameEvent, []byte) { +func (g EventGenerator) EnterNameEvent(time uint64, pid, tid uint32, oldname, newname string, traceID types.TraceId) (types.NameEvent, []byte, error) { ev := types.NameEvent{ EventType: types.ENTER_NAME_EVENT, TraceId: traceID, @@ -136,10 +143,11 @@ func (g EventGenerator) EnterNameEvent(time uint64, pid, tid uint32, oldname, ne } copy(ev.Oldname[:], oldname) copy(ev.Newname[:], newname) - return ev, mustBytes(&ev) + raw, err := eventBytes(&ev) + return ev, raw, err } -func (g EventGenerator) EnterFcntlEvent(time uint64, pid, tid uint32, fd uint32, cmd uint32, arg uint64) (types.FcntlEvent, []byte) { +func (g EventGenerator) EnterFcntlEvent(time uint64, pid, tid uint32, fd uint32, cmd uint32, arg uint64) (types.FcntlEvent, []byte, error) { ev := types.FcntlEvent{ EventType: types.ENTER_FCNTL_EVENT, TraceId: types.SYS_ENTER_FCNTL, @@ -150,10 +158,11 @@ func (g EventGenerator) EnterFcntlEvent(time uint64, pid, tid uint32, fd uint32, Cmd: cmd, Arg: arg, } - return ev, mustBytes(&ev) + raw, err := eventBytes(&ev) + return ev, raw, err } -func (g EventGenerator) EnterDup3Event(time uint64, pid, tid uint32, fd int32, flags int32) (types.Dup3Event, []byte) { +func (g EventGenerator) EnterDup3Event(time uint64, pid, tid uint32, fd int32, flags int32) (types.Dup3Event, []byte, error) { ev := types.Dup3Event{ EventType: types.ENTER_DUP3_EVENT, TraceId: types.SYS_ENTER_DUP3, @@ -163,10 +172,11 @@ func (g EventGenerator) EnterDup3Event(time uint64, pid, tid uint32, fd int32, f Fd: fd, Flags: flags, } - return ev, mustBytes(&ev) + raw, err := eventBytes(&ev) + return ev, raw, err } -func (g EventGenerator) EnterOpenByHandleAtEvent(time uint64, pid, tid uint32, flags int32) (types.OpenByHandleAtEvent, []byte) { +func (g EventGenerator) EnterOpenByHandleAtEvent(time uint64, pid, tid uint32, flags int32) (types.OpenByHandleAtEvent, []byte, error) { ev := types.OpenByHandleAtEvent{ EventType: types.ENTER_OPEN_BY_HANDLE_AT_EVENT, TraceId: types.SYS_ENTER_OPEN_BY_HANDLE_AT, @@ -175,49 +185,92 @@ func (g EventGenerator) EnterOpenByHandleAtEvent(time uint64, pid, tid uint32, f Tid: tid, Flags: flags, } - return ev, mustBytes(&ev) + raw, err := eventBytes(&ev) + return ev, raw, err } -func (g EventGenerator) OpenPair(time uint64, pid, tid uint32) ([]byte, []byte) { - _, enter := g.EnterOpenEvent(time, pid, tid) - _, exit := g.ExitOpenEvent(time+g.pairDelta(), pid, tid) - return enter, exit +func (g EventGenerator) OpenPair(time uint64, pid, tid uint32) ([]byte, []byte, error) { + _, enter, err := g.EnterOpenEvent(time, pid, tid) + if err != nil { + return nil, nil, err + } + _, exit, err := g.ExitOpenEvent(time+g.pairDelta(), pid, tid) + if err != nil { + return nil, nil, err + } + return enter, exit, nil } -func (g EventGenerator) FdPair(time uint64, pid, tid uint32, fd int32, enterTraceID, exitTraceID types.TraceId, ret int64) ([]byte, []byte) { - _, enter := g.EnterFdEvent(time, pid, tid, fd, enterTraceID) - _, exit := g.ExitRetEvent(time+g.pairDelta(), pid, tid, exitTraceID, ret) - return enter, exit +func (g EventGenerator) FdPair(time uint64, pid, tid uint32, fd int32, enterTraceID, exitTraceID types.TraceId, ret int64) ([]byte, []byte, error) { + _, enter, err := g.EnterFdEvent(time, pid, tid, fd, enterTraceID) + if err != nil { + return nil, nil, err + } + _, exit, err := g.ExitRetEvent(time+g.pairDelta(), pid, tid, exitTraceID, ret) + if err != nil { + return nil, nil, err + } + return enter, exit, nil } -func (g EventGenerator) NullPair(time uint64, pid, tid uint32, enterTraceID, exitTraceID types.TraceId) ([]byte, []byte) { - _, enter := g.EnterNullEvent(time, pid, tid, enterTraceID) - _, exit := g.ExitNullEvent(time+g.pairDelta(), pid, tid, exitTraceID) - return enter, exit +func (g EventGenerator) NullPair(time uint64, pid, tid uint32, enterTraceID, exitTraceID types.TraceId) ([]byte, []byte, error) { + _, enter, err := g.EnterNullEvent(time, pid, tid, enterTraceID) + if err != nil { + return nil, nil, err + } + _, exit, err := g.ExitNullEvent(time+g.pairDelta(), pid, tid, exitTraceID) + if err != nil { + return nil, nil, err + } + return enter, exit, nil } -func (g EventGenerator) PathPair(time uint64, pid, tid uint32, pathname string, enterTraceID, exitTraceID types.TraceId, ret int64) ([]byte, []byte) { - _, enter := g.EnterPathEvent(time, pid, tid, pathname, enterTraceID) - _, exit := g.ExitRetEvent(time+g.pairDelta(), pid, tid, exitTraceID, ret) - return enter, exit +func (g EventGenerator) PathPair(time uint64, pid, tid uint32, pathname string, enterTraceID, exitTraceID types.TraceId, ret int64) ([]byte, []byte, error) { + _, enter, err := g.EnterPathEvent(time, pid, tid, pathname, enterTraceID) + if err != nil { + return nil, nil, err + } + _, exit, err := g.ExitRetEvent(time+g.pairDelta(), pid, tid, exitTraceID, ret) + if err != nil { + return nil, nil, err + } + return enter, exit, nil } -func (g EventGenerator) NamePair(time uint64, pid, tid uint32, oldname, newname string, enterTraceID, exitTraceID types.TraceId, ret int64) ([]byte, []byte) { - _, enter := g.EnterNameEvent(time, pid, tid, oldname, newname, enterTraceID) - _, exit := g.ExitRetEvent(time+g.pairDelta(), pid, tid, exitTraceID, ret) - return enter, exit +func (g EventGenerator) NamePair(time uint64, pid, tid uint32, oldname, newname string, enterTraceID, exitTraceID types.TraceId, ret int64) ([]byte, []byte, error) { + _, enter, err := g.EnterNameEvent(time, pid, tid, oldname, newname, enterTraceID) + if err != nil { + return nil, nil, err + } + _, exit, err := g.ExitRetEvent(time+g.pairDelta(), pid, tid, exitTraceID, ret) + if err != nil { + return nil, nil, err + } + return enter, exit, nil } -func (g EventGenerator) FcntlPair(time uint64, pid, tid uint32, fd uint32, cmd uint32, arg uint64, exitTraceID types.TraceId, ret int64) ([]byte, []byte) { - _, enter := g.EnterFcntlEvent(time, pid, tid, fd, cmd, arg) - _, exit := g.ExitRetEvent(time+g.pairDelta(), pid, tid, exitTraceID, ret) - return enter, exit +func (g EventGenerator) FcntlPair(time uint64, pid, tid uint32, fd uint32, cmd uint32, arg uint64, exitTraceID types.TraceId, ret int64) ([]byte, []byte, error) { + _, enter, err := g.EnterFcntlEvent(time, pid, tid, fd, cmd, arg) + if err != nil { + return nil, nil, err + } + _, exit, err := g.ExitRetEvent(time+g.pairDelta(), pid, tid, exitTraceID, ret) + if err != nil { + return nil, nil, err + } + return enter, exit, nil } -func (g EventGenerator) Dup3Pair(time uint64, pid, tid uint32, fd int32, flags int32, exitTraceID types.TraceId, ret int64) ([]byte, []byte) { - _, enter := g.EnterDup3Event(time, pid, tid, fd, flags) - _, exit := g.ExitRetEvent(time+g.pairDelta(), pid, tid, exitTraceID, ret) - return enter, exit +func (g EventGenerator) Dup3Pair(time uint64, pid, tid uint32, fd int32, flags int32, exitTraceID types.TraceId, ret int64) ([]byte, []byte, error) { + _, enter, err := g.EnterDup3Event(time, pid, tid, fd, flags) + if err != nil { + return nil, nil, err + } + _, exit, err := g.ExitRetEvent(time+g.pairDelta(), pid, tid, exitTraceID, ret) + if err != nil { + return nil, nil, err + } + return enter, exit, nil } func (g EventGenerator) pairDelta() uint64 { @@ -227,12 +280,9 @@ func (g EventGenerator) pairDelta() uint64 { return g.PairDelta } -func mustBytes(event interface{ Bytes() ([]byte, error) }) []byte { +func eventBytes(event interface{ Bytes() ([]byte, error) }) ([]byte, error) { raw, err := event.Bytes() - if err != nil { - panic(fmt.Sprintf("event serialization failed: %v", err)) - } - return raw + return raw, err } func retType(traceID types.TraceId) uint32 { diff --git a/internal/benchutil/eventgen_test.go b/internal/benchutil/eventgen_test.go index 32e9ce3..bf3def3 100644 --- a/internal/benchutil/eventgen_test.go +++ b/internal/benchutil/eventgen_test.go @@ -17,7 +17,8 @@ func TestEventGeneratorEventMethodsRoundTrip(t *testing.T) { ) t.Run("EnterOpenEvent", func(t *testing.T) { - want, raw := gen.EnterOpenEvent(time, pid, tid) + want, raw, err := gen.EnterOpenEvent(time, pid, tid) + requireNoError(t, err) got := types.NewOpenEvent(raw) defer got.Recycle() if !want.Equals(got) { @@ -26,7 +27,8 @@ func TestEventGeneratorEventMethodsRoundTrip(t *testing.T) { }) t.Run("ExitOpenEvent", func(t *testing.T) { - want, raw := gen.ExitOpenEvent(time, pid, tid) + want, raw, err := gen.ExitOpenEvent(time, pid, tid) + requireNoError(t, err) got := types.NewRetEvent(raw) defer got.Recycle() if !want.Equals(got) { @@ -35,7 +37,8 @@ func TestEventGeneratorEventMethodsRoundTrip(t *testing.T) { }) t.Run("EnterFdEvent", func(t *testing.T) { - want, raw := gen.EnterFdEvent(time, pid, tid, 11, types.SYS_ENTER_READ) + want, raw, err := gen.EnterFdEvent(time, pid, tid, 11, types.SYS_ENTER_READ) + requireNoError(t, err) got := types.NewFdEvent(raw) defer got.Recycle() if !want.Equals(got) { @@ -44,7 +47,8 @@ func TestEventGeneratorEventMethodsRoundTrip(t *testing.T) { }) t.Run("ExitFdEvent", func(t *testing.T) { - want, raw := gen.ExitFdEvent(time, pid, tid, 11, types.SYS_EXIT_CLOSE) + want, raw, err := gen.ExitFdEvent(time, pid, tid, 11, types.SYS_EXIT_CLOSE) + requireNoError(t, err) got := types.NewFdEvent(raw) defer got.Recycle() if !want.Equals(got) { @@ -53,7 +57,8 @@ func TestEventGeneratorEventMethodsRoundTrip(t *testing.T) { }) t.Run("EnterNullEvent", func(t *testing.T) { - want, raw := gen.EnterNullEvent(time, pid, tid, types.SYS_ENTER_SYNC) + want, raw, err := gen.EnterNullEvent(time, pid, tid, types.SYS_ENTER_SYNC) + requireNoError(t, err) got := types.NewNullEvent(raw) defer got.Recycle() if !want.Equals(got) { @@ -62,7 +67,8 @@ func TestEventGeneratorEventMethodsRoundTrip(t *testing.T) { }) t.Run("ExitNullEvent", func(t *testing.T) { - want, raw := gen.ExitNullEvent(time, pid, tid, types.SYS_EXIT_SYNC) + want, raw, err := gen.ExitNullEvent(time, pid, tid, types.SYS_EXIT_SYNC) + requireNoError(t, err) got := types.NewNullEvent(raw) defer got.Recycle() if !want.Equals(got) { @@ -71,7 +77,8 @@ func TestEventGeneratorEventMethodsRoundTrip(t *testing.T) { }) t.Run("ExitRetEvent", func(t *testing.T) { - want, raw := gen.ExitRetEvent(time, pid, tid, types.SYS_EXIT_READ, 256) + want, raw, err := gen.ExitRetEvent(time, pid, tid, types.SYS_EXIT_READ, 256) + requireNoError(t, err) got := types.NewRetEvent(raw) defer got.Recycle() if !want.Equals(got) { @@ -83,7 +90,8 @@ func TestEventGeneratorEventMethodsRoundTrip(t *testing.T) { }) t.Run("EnterPathEvent", func(t *testing.T) { - want, raw := gen.EnterPathEvent(time, pid, tid, "/tmp/path", types.SYS_ENTER_MKDIR) + want, raw, err := gen.EnterPathEvent(time, pid, tid, "/tmp/path", types.SYS_ENTER_MKDIR) + requireNoError(t, err) got := types.NewPathEvent(raw) defer got.Recycle() if !want.Equals(got) { @@ -92,7 +100,8 @@ func TestEventGeneratorEventMethodsRoundTrip(t *testing.T) { }) t.Run("EnterNameEvent", func(t *testing.T) { - want, raw := gen.EnterNameEvent(time, pid, tid, "/tmp/old", "/tmp/new", types.SYS_ENTER_RENAME) + want, raw, err := gen.EnterNameEvent(time, pid, tid, "/tmp/old", "/tmp/new", types.SYS_ENTER_RENAME) + requireNoError(t, err) got := types.NewNameEvent(raw) defer got.Recycle() if !want.Equals(got) { @@ -101,7 +110,8 @@ func TestEventGeneratorEventMethodsRoundTrip(t *testing.T) { }) t.Run("EnterFcntlEvent", func(t *testing.T) { - want, raw := gen.EnterFcntlEvent(time, pid, tid, 33, syscall.F_SETFL, syscall.O_NONBLOCK) + want, raw, err := gen.EnterFcntlEvent(time, pid, tid, 33, syscall.F_SETFL, syscall.O_NONBLOCK) + requireNoError(t, err) got := types.NewFcntlEvent(raw) defer got.Recycle() if !want.Equals(got) { @@ -110,7 +120,8 @@ func TestEventGeneratorEventMethodsRoundTrip(t *testing.T) { }) t.Run("EnterDup3Event", func(t *testing.T) { - want, raw := gen.EnterDup3Event(time, pid, tid, 44, syscall.O_CLOEXEC) + want, raw, err := gen.EnterDup3Event(time, pid, tid, 44, syscall.O_CLOEXEC) + requireNoError(t, err) got := types.NewDup3Event(raw) defer got.Recycle() if !want.Equals(got) { @@ -119,7 +130,8 @@ func TestEventGeneratorEventMethodsRoundTrip(t *testing.T) { }) t.Run("EnterOpenByHandleAtEvent", func(t *testing.T) { - want, raw := gen.EnterOpenByHandleAtEvent(time, pid, tid, syscall.O_RDONLY) + want, raw, err := gen.EnterOpenByHandleAtEvent(time, pid, tid, syscall.O_RDONLY) + requireNoError(t, err) got := types.NewOpenByHandleAtEvent(raw) defer got.Recycle() if !want.Equals(got) { @@ -138,7 +150,8 @@ func TestEventGeneratorPairMethods(t *testing.T) { ) t.Run("OpenPair", func(t *testing.T) { - enterRaw, exitRaw := gen.OpenPair(start, pid, tid) + enterRaw, exitRaw, err := gen.OpenPair(start, pid, tid) + requireNoError(t, err) enter := types.NewOpenEvent(enterRaw) defer enter.Recycle() exit := types.NewRetEvent(exitRaw) @@ -151,7 +164,8 @@ func TestEventGeneratorPairMethods(t *testing.T) { }) t.Run("FdPair", func(t *testing.T) { - enterRaw, exitRaw := gen.FdPair(start, pid, tid, 9, types.SYS_ENTER_READ, types.SYS_EXIT_READ, 128) + enterRaw, exitRaw, err := gen.FdPair(start, pid, tid, 9, types.SYS_ENTER_READ, types.SYS_EXIT_READ, 128) + requireNoError(t, err) enter := types.NewFdEvent(enterRaw) defer enter.Recycle() exit := types.NewRetEvent(exitRaw) @@ -167,7 +181,8 @@ func TestEventGeneratorPairMethods(t *testing.T) { }) t.Run("NullPair", func(t *testing.T) { - enterRaw, exitRaw := gen.NullPair(start, pid, tid, types.SYS_ENTER_SYNC, types.SYS_EXIT_SYNC) + enterRaw, exitRaw, err := gen.NullPair(start, pid, tid, types.SYS_ENTER_SYNC, types.SYS_EXIT_SYNC) + requireNoError(t, err) enter := types.NewNullEvent(enterRaw) defer enter.Recycle() exit := types.NewNullEvent(exitRaw) @@ -180,7 +195,8 @@ func TestEventGeneratorPairMethods(t *testing.T) { }) t.Run("PathPair", func(t *testing.T) { - enterRaw, exitRaw := gen.PathPair(start, pid, tid, "/tmp/p", types.SYS_ENTER_MKDIR, types.SYS_EXIT_MKDIR, 0) + enterRaw, exitRaw, err := gen.PathPair(start, pid, tid, "/tmp/p", types.SYS_ENTER_MKDIR, types.SYS_EXIT_MKDIR, 0) + requireNoError(t, err) enter := types.NewPathEvent(enterRaw) defer enter.Recycle() exit := types.NewRetEvent(exitRaw) @@ -193,7 +209,8 @@ func TestEventGeneratorPairMethods(t *testing.T) { }) t.Run("NamePair", func(t *testing.T) { - enterRaw, exitRaw := gen.NamePair(start, pid, tid, "old", "new", types.SYS_ENTER_RENAME, types.SYS_EXIT_RENAME, 0) + enterRaw, exitRaw, err := gen.NamePair(start, pid, tid, "old", "new", types.SYS_ENTER_RENAME, types.SYS_EXIT_RENAME, 0) + requireNoError(t, err) enter := types.NewNameEvent(enterRaw) defer enter.Recycle() exit := types.NewRetEvent(exitRaw) @@ -206,7 +223,8 @@ func TestEventGeneratorPairMethods(t *testing.T) { }) t.Run("FcntlPair", func(t *testing.T) { - enterRaw, exitRaw := gen.FcntlPair(start, pid, tid, 5, syscall.F_SETFL, syscall.O_NONBLOCK, types.SYS_EXIT_FCNTL, 0) + enterRaw, exitRaw, err := gen.FcntlPair(start, pid, tid, 5, syscall.F_SETFL, syscall.O_NONBLOCK, types.SYS_EXIT_FCNTL, 0) + requireNoError(t, err) enter := types.NewFcntlEvent(enterRaw) defer enter.Recycle() exit := types.NewRetEvent(exitRaw) @@ -219,7 +237,8 @@ func TestEventGeneratorPairMethods(t *testing.T) { }) t.Run("Dup3Pair", func(t *testing.T) { - enterRaw, exitRaw := gen.Dup3Pair(start, pid, tid, 8, syscall.O_CLOEXEC, types.SYS_EXIT_DUP3, 9) + enterRaw, exitRaw, err := gen.Dup3Pair(start, pid, tid, 8, syscall.O_CLOEXEC, types.SYS_EXIT_DUP3, 9) + requireNoError(t, err) enter := types.NewDup3Event(enterRaw) defer enter.Recycle() exit := types.NewRetEvent(exitRaw) @@ -241,7 +260,8 @@ func TestEventGeneratorPairDeltaDefaultAndCustom(t *testing.T) { t.Run("default", func(t *testing.T) { gen := EventGenerator{} - enterRaw, exitRaw := gen.OpenPair(start, pid, tid) + enterRaw, exitRaw, err := gen.OpenPair(start, pid, tid) + requireNoError(t, err) enter := types.NewOpenEvent(enterRaw) defer enter.Recycle() exit := types.NewRetEvent(exitRaw) @@ -254,7 +274,8 @@ func TestEventGeneratorPairDeltaDefaultAndCustom(t *testing.T) { t.Run("custom", func(t *testing.T) { const customDelta uint64 = 7 gen := EventGenerator{PairDelta: customDelta} - enterRaw, exitRaw := gen.OpenPair(start, pid, tid) + enterRaw, exitRaw, err := gen.OpenPair(start, pid, tid) + requireNoError(t, err) enter := types.NewOpenEvent(enterRaw) defer enter.Recycle() exit := types.NewRetEvent(exitRaw) @@ -280,3 +301,10 @@ func assertPairTimingAndIdentity(t *testing.T, start uint64, pid, tid uint32, en t.Fatalf("exit identity mismatch: pid/tid = %d/%d, want %d/%d", exitPid, exitTid, pid, tid) } } + +func requireNoError(t *testing.T, err error) { + t.Helper() + if err != nil { + t.Fatalf("unexpected error: %v", err) + } +} diff --git a/internal/benchutil/eventmix.go b/internal/benchutil/eventmix.go index 1057c0e..914bb93 100644 --- a/internal/benchutil/eventmix.go +++ b/internal/benchutil/eventmix.go @@ -101,9 +101,9 @@ var DiverseAllTypes = EventMix{ Seed: defaultMixSeed, } -func (m EventMix) GenerateStream(gen EventGenerator, n, numThreads int) [][]byte { +func (m EventMix) GenerateStream(gen EventGenerator, n, numThreads int) ([][]byte, error) { if n <= 0 { - return nil + return nil, nil } threadCount := numThreads @@ -123,12 +123,15 @@ func (m EventMix) GenerateStream(gen EventGenerator, n, numThreads int) [][]byte tid := defaultBaseTid + uint32(threadIdx) fd := fdFor(threadIdx, i) event := choose(entries, totalWeight, rng) - enter, exit := event.pair(gen, nextTime, pid, tid, fd, i) + enter, exit, err := event.pair(gen, nextTime, pid, tid, fd, i) + if err != nil { + return nil, fmt.Errorf("generate event %v pair: %w", event, err) + } stream = append(stream, enter, exit) nextTime += gen.pairDelta() + 1 } - return stream + return stream, nil } func choose(entries []MixEntry, totalWeight int, rng *rand.Rand) MixEvent { @@ -181,7 +184,7 @@ func sumWeights(entries []MixEntry) int { return total } -func (e MixEvent) pair(gen EventGenerator, time uint64, pid, tid uint32, fd int32, seq int) ([]byte, []byte) { +func (e MixEvent) pair(gen EventGenerator, time uint64, pid, tid uint32, fd int32, seq int) ([]byte, []byte, error) { switch e { case MixRead: return gen.FdPair(time, pid, tid, fd, types.SYS_ENTER_READ, types.SYS_EXIT_READ, 128) @@ -190,9 +193,15 @@ func (e MixEvent) pair(gen EventGenerator, time uint64, pid, tid uint32, fd int3 case MixOpen: return gen.OpenPair(time, pid, tid) case MixClose: - _, enter := gen.EnterFdEvent(time, pid, tid, fd, types.SYS_ENTER_CLOSE) - _, exit := gen.ExitFdEvent(time+gen.pairDelta(), pid, tid, fd, types.SYS_EXIT_CLOSE) - return enter, exit + _, enter, err := gen.EnterFdEvent(time, pid, tid, fd, types.SYS_ENTER_CLOSE) + if err != nil { + return nil, nil, err + } + _, exit, err := gen.ExitFdEvent(time+gen.pairDelta(), pid, tid, fd, types.SYS_EXIT_CLOSE) + if err != nil { + return nil, nil, err + } + return enter, exit, nil case MixStat: path := fmt.Sprintf("/tmp/ior-stat-%d-%d", tid, seq) return gen.PathPair(time, pid, tid, path, types.SYS_ENTER_NEWSTAT, types.SYS_EXIT_NEWSTAT, 0) @@ -222,9 +231,15 @@ func (e MixEvent) pair(gen EventGenerator, time uint64, pid, tid uint32, fd int3 case MixDup3: return gen.Dup3Pair(time, pid, tid, fd, syscall.O_CLOEXEC, types.SYS_EXIT_DUP3, int64(fd+1)) case MixOpenByHandleAt: - _, enter := gen.EnterOpenByHandleAtEvent(time, pid, tid, syscall.O_RDWR) - _, exit := gen.ExitRetEvent(time+gen.pairDelta(), pid, tid, types.SYS_EXIT_OPEN_BY_HANDLE_AT, int64(fd)) - return enter, exit + _, enter, err := gen.EnterOpenByHandleAtEvent(time, pid, tid, syscall.O_RDWR) + if err != nil { + return nil, nil, err + } + _, exit, err := gen.ExitRetEvent(time+gen.pairDelta(), pid, tid, types.SYS_EXIT_OPEN_BY_HANDLE_AT, int64(fd)) + if err != nil { + return nil, nil, err + } + return enter, exit, nil default: return gen.NullPair(time, pid, tid, types.SYS_ENTER_SYNC, types.SYS_EXIT_SYNC) } -- cgit v1.2.3