...
1 package glog
2
3 import (
4 "flag"
5 "io/ioutil"
6 "runtime"
7 "sync"
8 "sync/atomic"
9 "testing"
10 "time"
11 )
12
13
14
15 type discarder struct {
16 }
17
18 func (d *discarder) Write(data []byte) (int, error) {
19 return len(data), nil
20 }
21
22 func (d *discarder) Flush() error {
23 return nil
24 }
25
26 func (d *discarder) Sync() error {
27 time.Sleep(10 * time.Millisecond)
28 return nil
29 }
30
31 func (d *discarder) filenames() []string {
32 return nil
33 }
34
35
36 func (s *fileSink) newDiscarders() severityWriters {
37 return s.swap(severityWriters{new(discarder), new(discarder), new(discarder), new(discarder)})
38 }
39
40 func discardStderr() func() {
41 se := sinks.stderr.w
42 sinks.stderr.w = ioutil.Discard
43 return func() { sinks.stderr.w = se }
44 }
45
46 const message = "benchmark log message"
47
48 func benchmarkLog(b *testing.B, log func(...any)) {
49 defer sinks.file.swap(sinks.file.newDiscarders())
50 defer discardStderr()()
51 b.ResetTimer()
52 for i := 0; i < b.N; i++ {
53 log(message)
54 }
55 b.StopTimer()
56 }
57
58 func benchmarkLogConcurrent(b *testing.B, log func(...any)) {
59 defer sinks.file.swap(sinks.file.newDiscarders())
60 defer discardStderr()()
61 b.ResetTimer()
62 concurrency := runtime.GOMAXPROCS(0)
63 var wg sync.WaitGroup
64 wg.Add(concurrency)
65 for i := 0; i < concurrency; i++ {
66 go func() {
67 for i := 0; i < b.N; i++ {
68 log(message)
69 }
70 wg.Done()
71 }()
72 }
73 wg.Wait()
74 b.StopTimer()
75 }
76
77 func BenchmarkInfo(b *testing.B) {
78 benchmarkLog(b, Info)
79 }
80
81 func BenchmarkInfoConcurrent(b *testing.B) {
82 benchmarkLogConcurrent(b, Info)
83 }
84
85 func BenchmarkWarning(b *testing.B) {
86 benchmarkLog(b, Warning)
87 }
88
89 func BenchmarkWarningConcurrent(b *testing.B) {
90 benchmarkLogConcurrent(b, Warning)
91 }
92
93 func BenchmarkError(b *testing.B) {
94 benchmarkLog(b, Error)
95 }
96
97 func BenchmarkErrorConcurrent(b *testing.B) {
98 benchmarkLogConcurrent(b, Error)
99 }
100
101 func mixer() func(...any) {
102 var i int64
103 return func(args ...any) {
104 n := atomic.AddInt64(&i, 1)
105 switch {
106 case n%10000 == 0:
107 Error(args...)
108 case n%1000 == 0:
109 Warning(args...)
110 default:
111 Info(args...)
112 }
113 }
114 }
115
116 func BenchmarkMix(b *testing.B) {
117 benchmarkLog(b, mixer())
118 }
119
120 func BenchmarkMixConcurrent(b *testing.B) {
121 benchmarkLogConcurrent(b, mixer())
122 }
123
124 func BenchmarkVLogDisabled(b *testing.B) {
125 benchmarkLog(b, vlog)
126 }
127
128 func BenchmarkVLogDisabledConcurrent(b *testing.B) {
129 benchmarkLogConcurrent(b, vlog)
130 }
131
132 func BenchmarkVLogModuleFlagSet(b *testing.B) {
133 defer withVmodule("nonexistant=5")()
134 benchmarkLog(b, vlog)
135 }
136
137 func BenchmarkVLogModuleFlagSetConcurrent(b *testing.B) {
138 defer withVmodule("nonexistant=5")()
139 benchmarkLogConcurrent(b, vlog)
140 }
141
142 func BenchmarkVLogEnabled(b *testing.B) {
143 defer withVmodule("glog_bench_test=5")()
144 if got := bool(V(3)); got != true {
145 b.Fatalf("V(3) == %v, want %v", got, true)
146 }
147 benchmarkLog(b, vlog)
148 }
149
150 func BenchmarkVLogEnabledConcurrent(b *testing.B) {
151 defer withVmodule("glog_bench_test=5")()
152 benchmarkLogConcurrent(b, vlog)
153 }
154
155 func vlog(args ...any) {
156 V(3).Info(args)
157 }
158
159 func withVmodule(val string) func() {
160 if err := flag.Set("vmodule", val); err != nil {
161 panic(err)
162 }
163 return func() { flag.Set("vmodule", "") }
164 }
165
View as plain text