summaryrefslogtreecommitdiff
path: root/internal
diff options
context:
space:
mode:
Diffstat (limited to 'internal')
-rw-r--r--internal/bench_components_test.go363
1 files changed, 363 insertions, 0 deletions
diff --git a/internal/bench_components_test.go b/internal/bench_components_test.go
new file mode 100644
index 0000000..1f9ccb5
--- /dev/null
+++ b/internal/bench_components_test.go
@@ -0,0 +1,363 @@
+package internal
+
+import (
+ "fmt"
+ "syscall"
+ "testing"
+
+ "ior/internal/benchutil"
+ "ior/internal/event"
+ "ior/internal/file"
+ "ior/internal/types"
+)
+
+const (
+ componentBenchPID uint32 = 4242
+ componentBenchTID uint32 = 4343
+)
+
+type recyclable interface {
+ Recycle()
+}
+
+func BenchmarkDeserializeOpenEvent(b *testing.B) {
+ gen := benchutil.NewEventGenerator()
+ _, raw := gen.EnterOpenEvent(1, componentBenchPID, componentBenchTID)
+ benchmarkDeserialize(b, raw, types.NewOpenEvent)
+}
+
+func BenchmarkDeserializeFdEvent(b *testing.B) {
+ gen := benchutil.NewEventGenerator()
+ _, raw := gen.EnterFdEvent(1, componentBenchPID, componentBenchTID, 12, types.SYS_ENTER_READ)
+ benchmarkDeserialize(b, raw, types.NewFdEvent)
+}
+
+func BenchmarkDeserializeNullEvent(b *testing.B) {
+ gen := benchutil.NewEventGenerator()
+ _, raw := gen.EnterNullEvent(1, componentBenchPID, componentBenchTID, types.SYS_ENTER_SYNC)
+ benchmarkDeserialize(b, raw, types.NewNullEvent)
+}
+
+func BenchmarkDeserializeRetEvent(b *testing.B) {
+ gen := benchutil.NewEventGenerator()
+ _, raw := gen.ExitRetEvent(1, componentBenchPID, componentBenchTID, types.SYS_EXIT_READ, 64)
+ 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)
+ 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)
+ 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)
+ benchmarkDeserialize(b, raw, types.NewFcntlEvent)
+}
+
+func BenchmarkDeserializeDup3Event(b *testing.B) {
+ gen := benchutil.NewEventGenerator()
+ _, raw := gen.EnterDup3Event(1, componentBenchPID, componentBenchTID, 8, syscall.O_CLOEXEC)
+ benchmarkDeserialize(b, raw, types.NewDup3Event)
+}
+
+func BenchmarkRawHandlerLookup(b *testing.B) {
+ b.ReportAllocs()
+
+ el := newEventLoop(eventLoopConfig{})
+ eventTypes := []types.EventType{
+ types.ENTER_OPEN_EVENT,
+ types.EXIT_OPEN_EVENT,
+ types.ENTER_FD_EVENT,
+ types.EXIT_FD_EVENT,
+ types.ENTER_NULL_EVENT,
+ types.EXIT_NULL_EVENT,
+ types.EXIT_RET_EVENT,
+ types.ENTER_NAME_EVENT,
+ types.ENTER_PATH_EVENT,
+ types.ENTER_FCNTL_EVENT,
+ types.ENTER_DUP3_EVENT,
+ }
+
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ _ = el.rawHandlers[eventTypes[i%len(eventTypes)]]
+ }
+}
+
+func BenchmarkTracepointEntered(b *testing.B) {
+ b.ReportAllocs()
+
+ gen := benchutil.NewEventGenerator()
+ _, raw := gen.EnterOpenEvent(1, componentBenchPID, componentBenchTID)
+ el := newComponentBenchEventLoop(componentBenchTID)
+
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ enterEv := types.NewOpenEvent(raw)
+ el.tracepointEntered(enterEv)
+ if ep, ok := el.enterEvs[componentBenchTID]; ok {
+ delete(el.enterEvs, componentBenchTID)
+ // tracepointEntered stores only EnterEv; provide a placeholder so Pair.Recycle can return to the pool.
+ ep.ExitEv = &types.NullEvent{}
+ ep.Recycle()
+ }
+ }
+}
+
+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)
+ el := newComponentBenchEventLoop(componentBenchTID)
+ out := make(chan *event.Pair, 1)
+
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ enterEv := types.NewNullEvent(enterRaw)
+ el.enterEvs[componentBenchTID] = event.NewPair(enterEv)
+ exitEv := types.NewNullEvent(exitRaw)
+ el.tracepointExited(exitEv, out)
+ (<-out).Recycle()
+ }
+}
+
+func BenchmarkHandleOpenExit(b *testing.B) {
+ b.ReportAllocs()
+
+ gen := benchutil.NewEventGenerator()
+ enterTemplate, _ := gen.EnterOpenEvent(1, componentBenchPID, componentBenchTID)
+ exitTemplate, _ := gen.ExitOpenEvent(2, componentBenchPID, componentBenchTID)
+ el := newComponentBenchEventLoop(componentBenchTID)
+
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ enter := enterTemplate
+ enter.Time = uint64(i*2 + 1)
+ exit := exitTemplate
+ exit.Time = uint64(i*2 + 2)
+ ep := event.NewPair(&enter)
+ ep.ExitEv = &exit
+ if !el.handleOpenExit(ep, &enter) {
+ b.Fatal("handleOpenExit returned false")
+ }
+ ep.Recycle()
+ }
+}
+
+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)
+ el := newComponentBenchEventLoop(componentBenchTID)
+ el.fdState().set(99, file.NewFd(99, "/tmp/fd", syscall.O_RDONLY))
+
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ enter := enterTemplate
+ enter.Time = uint64(i*2 + 1)
+ exit := exitTemplate
+ exit.Time = uint64(i*2 + 2)
+ ep := event.NewPair(&enter)
+ ep.ExitEv = &exit
+ if !el.handleFdExit(ep, &enter) {
+ b.Fatal("handleFdExit returned false")
+ }
+ ep.Recycle()
+ }
+}
+
+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)
+ el := newComponentBenchEventLoop(componentBenchTID)
+
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ enter := enterTemplate
+ enter.Time = uint64(i*2 + 1)
+ exit := exitTemplate
+ exit.Time = uint64(i*2 + 2)
+ ep := event.NewPair(&enter)
+ ep.ExitEv = &exit
+ if !el.handlePathExit(ep, &enter) {
+ b.Fatal("handlePathExit returned false")
+ }
+ ep.Recycle()
+ }
+}
+
+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)
+ el := newComponentBenchEventLoop(componentBenchTID)
+
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ enter := enterTemplate
+ enter.Time = uint64(i*2 + 1)
+ exit := exitTemplate
+ exit.Time = uint64(i*2 + 2)
+ ep := event.NewPair(&enter)
+ ep.ExitEv = &exit
+ if !el.handleNameExit(ep, &enter) {
+ b.Fatal("handleNameExit returned false")
+ }
+ ep.Recycle()
+ }
+}
+
+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)
+ el := newComponentBenchEventLoop(componentBenchTID)
+
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ enter := enterTemplate
+ enter.Time = uint64(i*2 + 1)
+ exit := exitTemplate
+ exit.Time = uint64(i*2 + 2)
+ ep := event.NewPair(&enter)
+ ep.ExitEv = &exit
+ if !el.handleNullExit(ep, &enter) {
+ b.Fatal("handleNullExit returned false")
+ }
+ ep.Recycle()
+ }
+}
+
+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)
+ el := newComponentBenchEventLoop(componentBenchTID)
+ el.fdState().set(7, file.NewFd(7, "/tmp/fcntl", syscall.O_RDONLY))
+
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ enter := enterTemplate
+ enter.Time = uint64(i*2 + 1)
+ exit := exitTemplate
+ exit.Time = uint64(i*2 + 2)
+ ep := event.NewPair(&enter)
+ ep.ExitEv = &exit
+ if !el.handleFcntlExit(ep, &enter) {
+ b.Fatal("handleFcntlExit returned false")
+ }
+ ep.Recycle()
+ }
+}
+
+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)
+ el := newComponentBenchEventLoop(componentBenchTID)
+ el.fdState().set(9, file.NewFd(9, "/tmp/dup3", syscall.O_RDONLY))
+
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ enter := enterTemplate
+ enter.Time = uint64(i*2 + 1)
+ exit := exitTemplate
+ exit.Time = uint64(i*2 + 2)
+ ep := event.NewPair(&enter)
+ ep.ExitEv = &exit
+ if !el.handleDup3Exit(ep, &enter) {
+ b.Fatal("handleDup3Exit returned false")
+ }
+ ep.Recycle()
+ }
+}
+
+func BenchmarkFdTrackerGetSet(b *testing.B) {
+ b.ReportAllocs()
+
+ tracker := newFDTracker(nil)
+ fdFile := file.NewFd(11, "/tmp/tracker", syscall.O_RDONLY)
+
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ fd := int32(i % 1024)
+ tracker.set(fd, fdFile)
+ _, _ = tracker.get(fd)
+ }
+}
+
+func BenchmarkCommResolverCachedHit(b *testing.B) {
+ b.ReportAllocs()
+
+ resolver := newCommResolver(nil)
+ const tid = componentBenchTID
+ resolver.setCached(tid, "bench")
+
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ if resolver.comm(tid) == "" {
+ b.Fatal("unexpected cache miss")
+ }
+ }
+}
+
+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)
+
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ enter := enterTemplate
+ enter.Time = uint64(i*2 + 1)
+ exit := exitTemplate
+ exit.Time = uint64(i*2 + 2)
+ ep := event.NewPair(&enter)
+ ep.ExitEv = &exit
+ ep.Recycle()
+ }
+}
+
+func benchmarkDeserialize[T recyclable](b *testing.B, raw []byte, decode func([]byte) T) {
+ b.Helper()
+ b.ReportAllocs()
+
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ ev := decode(raw)
+ ev.Recycle()
+ }
+}
+
+func newComponentBenchEventLoop(tids ...uint32) *eventLoop {
+ el := newEventLoop(eventLoopConfig{})
+ for _, tid := range tids {
+ el.setCachedComm(tid, fmt.Sprintf("bench-%d", tid))
+ }
+ return el
+}