logs benchmark: really write through pipe

While the benchmark is focused on encoding, it becomes a bit more realistic
when actually passing the encoded data to the Linux kernel. Features like
output buffering are more likely to have a visible effect when invoking
syscalls.
This commit is contained in:
Patrick Ohly 2024-01-11 18:55:42 +01:00
parent 7f1a30f8d5
commit 04b772c661
2 changed files with 26 additions and 9 deletions

View File

@ -74,14 +74,16 @@ func BenchmarkEncoding(b *testing.B) {
state := klog.CaptureState() state := klog.CaptureState()
defer state.Restore() defer state.Restore()
var output bytesWritten // To make the tests a bit more realistic, at
// least do system calls during each write.
output := newBytesWritten(b, "/dev/null")
c := logsapi.NewLoggingConfiguration() c := logsapi.NewLoggingConfiguration()
c.Format = format c.Format = format
o := logsapi.LoggingOptions{ o := logsapi.LoggingOptions{
ErrorStream: &output, ErrorStream: output,
InfoStream: &output, InfoStream: output,
} }
klog.SetOutput(&output) klog.SetOutput(output)
defer func() { defer func() {
if err := logsapi.ResetForTest(nil); err != nil { if err := logsapi.ResetForTest(nil); err != nil {
b.Errorf("error resetting logsapi: %v", err) b.Errorf("error resetting logsapi: %v", err)
@ -108,7 +110,7 @@ func BenchmarkEncoding(b *testing.B) {
// Report messages/s instead of ns/op because "op" varies. // Report messages/s instead of ns/op because "op" varies.
b.ReportMetric(0, "ns/op") b.ReportMetric(0, "ns/op")
b.ReportMetric(float64(total)/duration.Seconds(), "msgs/s") b.ReportMetric(float64(total)/duration.Seconds(), "msgs/s")
fileSizes[filepath.Base(b.Name())] = int(output) fileSizes[filepath.Base(b.Name())] = int(output.bytesWritten)
} }
b.Run("printf", func(b *testing.B) { b.Run("printf", func(b *testing.B) {

View File

@ -18,6 +18,8 @@ package benchmark
import ( import (
"flag" "flag"
"os"
"testing"
"k8s.io/klog/v2" "k8s.io/klog/v2"
) )
@ -34,12 +36,25 @@ func init() {
flag.Set("stderrthreshold", "FATAL") flag.Set("stderrthreshold", "FATAL")
} }
type bytesWritten int64 func newBytesWritten(tb testing.TB, filename string) *bytesWritten {
out, err := os.Create(filename)
if err != nil {
tb.Fatalf("open fake output: %v", err)
}
tb.Cleanup(func() { _ = out.Close() })
return &bytesWritten{
out: out,
}
}
type bytesWritten struct {
out *os.File
bytesWritten int64
}
func (b *bytesWritten) Write(data []byte) (int, error) { func (b *bytesWritten) Write(data []byte) (int, error) {
l := len(data) b.bytesWritten += int64(len(data))
*b += bytesWritten(l) return b.out.Write(data)
return l, nil
} }
func printf(item logMessage) { func printf(item logMessage) {