github.com/newrelic/go-agent@v3.26.0+incompatible/internal_benchmark_test.go (about) 1 // Copyright 2020 New Relic Corporation. All rights reserved. 2 // SPDX-License-Identifier: Apache-2.0 3 4 package newrelic 5 6 import ( 7 "net/http" 8 "testing" 9 ) 10 11 var ( 12 sampleLicense = "0123456789012345678901234567890123456789" 13 ) 14 15 // BenchmarkMuxWithoutNewRelic acts as a control against the other mux 16 // benchmarks. 17 func BenchmarkMuxWithoutNewRelic(b *testing.B) { 18 mux := http.NewServeMux() 19 mux.HandleFunc(helloPath, handler) 20 21 w := newCompatibleResponseRecorder() 22 23 b.ResetTimer() 24 b.ReportAllocs() 25 26 for i := 0; i < b.N; i++ { 27 mux.ServeHTTP(w, helloRequest) 28 } 29 } 30 31 // BenchmarkMuxWithNewRelic shows the approximate overhead of instrumenting a 32 // request. The numbers here are approximate since this is a test app: rather 33 // than putting the transaction into a channel to be processed by another 34 // goroutine, the transaction is merged directly into a harvest. 35 func BenchmarkMuxWithNewRelic(b *testing.B) { 36 app := testApp(nil, nil, b) 37 mux := http.NewServeMux() 38 mux.HandleFunc(WrapHandleFunc(app, helloPath, handler)) 39 40 w := newCompatibleResponseRecorder() 41 42 b.ResetTimer() 43 b.ReportAllocs() 44 45 for i := 0; i < b.N; i++ { 46 mux.ServeHTTP(w, helloRequest) 47 } 48 } 49 50 // BenchmarkMuxWithNewRelic shows the overhead of instrumenting a request when 51 // the agent is disabled. 52 func BenchmarkMuxDisabledMode(b *testing.B) { 53 cfg := NewConfig("my app", sampleLicense) 54 cfg.Enabled = false 55 app, err := newApp(cfg) 56 if nil != err { 57 b.Fatal(err) 58 } 59 mux := http.NewServeMux() 60 mux.HandleFunc(WrapHandleFunc(app, helloPath, handler)) 61 62 w := newCompatibleResponseRecorder() 63 64 b.ResetTimer() 65 b.ReportAllocs() 66 67 for i := 0; i < b.N; i++ { 68 mux.ServeHTTP(w, helloRequest) 69 } 70 } 71 72 // BenchmarkTraceSegmentWithDefer shows the overhead of instrumenting a segment 73 // using defer. This and BenchmarkTraceSegmentNoDefer are extremely important: 74 // Timing functions and blocks of code should have minimal cost. 75 func BenchmarkTraceSegmentWithDefer(b *testing.B) { 76 cfg := NewConfig("my app", sampleLicense) 77 cfg.Enabled = false 78 app, err := newApp(cfg) 79 if nil != err { 80 b.Fatal(err) 81 } 82 txn := app.StartTransaction("my txn", nil, nil) 83 fn := func() { 84 defer StartSegment(txn, "alpha").End() 85 } 86 b.ResetTimer() 87 b.ReportAllocs() 88 for i := 0; i < b.N; i++ { 89 fn() 90 } 91 } 92 93 func BenchmarkTraceSegmentNoDefer(b *testing.B) { 94 cfg := NewConfig("my app", sampleLicense) 95 cfg.Enabled = false 96 app, err := newApp(cfg) 97 if nil != err { 98 b.Fatal(err) 99 } 100 txn := app.StartTransaction("my txn", nil, nil) 101 fn := func() { 102 s := StartSegment(txn, "alpha") 103 s.End() 104 } 105 b.ResetTimer() 106 b.ReportAllocs() 107 for i := 0; i < b.N; i++ { 108 fn() 109 } 110 } 111 112 func BenchmarkTraceSegmentZeroSegmentThreshold(b *testing.B) { 113 cfg := NewConfig("my app", sampleLicense) 114 cfg.Enabled = false 115 cfg.TransactionTracer.SegmentThreshold = 0 116 app, err := newApp(cfg) 117 if nil != err { 118 b.Fatal(err) 119 } 120 txn := app.StartTransaction("my txn", nil, nil) 121 fn := func() { 122 s := StartSegment(txn, "alpha") 123 s.End() 124 } 125 b.ResetTimer() 126 b.ReportAllocs() 127 for i := 0; i < b.N; i++ { 128 fn() 129 } 130 } 131 132 func BenchmarkDatastoreSegment(b *testing.B) { 133 cfg := NewConfig("my app", sampleLicense) 134 cfg.Enabled = false 135 app, err := newApp(cfg) 136 if nil != err { 137 b.Fatal(err) 138 } 139 txn := app.StartTransaction("my txn", nil, nil) 140 fn := func(txn Transaction) { 141 ds := DatastoreSegment{ 142 StartTime: txn.StartSegmentNow(), 143 Product: DatastoreMySQL, 144 Collection: "my_table", 145 Operation: "Select", 146 } 147 defer ds.End() 148 } 149 b.ResetTimer() 150 b.ReportAllocs() 151 for i := 0; i < b.N; i++ { 152 fn(txn) 153 } 154 } 155 156 func BenchmarkExternalSegment(b *testing.B) { 157 cfg := NewConfig("my app", sampleLicense) 158 cfg.Enabled = false 159 app, err := newApp(cfg) 160 if nil != err { 161 b.Fatal(err) 162 } 163 txn := app.StartTransaction("my txn", nil, nil) 164 fn := func(txn Transaction) { 165 es := &ExternalSegment{ 166 StartTime: txn.StartSegmentNow(), 167 URL: "http://example.com/", 168 } 169 defer es.End() 170 } 171 b.ResetTimer() 172 b.ReportAllocs() 173 for i := 0; i < b.N; i++ { 174 fn(txn) 175 } 176 } 177 178 func BenchmarkTxnWithSegment(b *testing.B) { 179 app := testApp(nil, nil, b) 180 181 b.ResetTimer() 182 b.ReportAllocs() 183 184 for i := 0; i < b.N; i++ { 185 txn := app.StartTransaction("my txn", nil, nil) 186 StartSegment(txn, "myFunction").End() 187 txn.End() 188 } 189 } 190 191 func BenchmarkTxnWithDatastore(b *testing.B) { 192 app := testApp(nil, nil, b) 193 194 b.ResetTimer() 195 b.ReportAllocs() 196 197 for i := 0; i < b.N; i++ { 198 txn := app.StartTransaction("my txn", nil, nil) 199 ds := &DatastoreSegment{ 200 StartTime: txn.StartSegmentNow(), 201 Product: DatastoreMySQL, 202 Collection: "my_table", 203 Operation: "Select", 204 } 205 ds.End() 206 txn.End() 207 } 208 } 209 210 func BenchmarkTxnWithExternal(b *testing.B) { 211 app := testApp(nil, nil, b) 212 213 b.ResetTimer() 214 b.ReportAllocs() 215 216 for i := 0; i < b.N; i++ { 217 txn := app.StartTransaction("my txn", nil, nil) 218 es := &ExternalSegment{ 219 StartTime: txn.StartSegmentNow(), 220 URL: "http://example.com", 221 } 222 es.End() 223 txn.End() 224 } 225 }