event: add benchmarks for context lookups

See how much it costs to look up the exporter in the context.

The results (see below) show that with a context chain of length 10,
doing a context lookup is about 20% slower than not.

go test -v -run XXX -bench BuildContext
goos: linux
goarch: amd64
pkg: golang.org/x/exp/event
cpu: Intel(R) Xeon(R) CPU @ 2.30GHz
BenchmarkBuildContext
BenchmarkBuildContext/depth_1
BenchmarkBuildContext/depth_1/with
BenchmarkBuildContext/depth_1/with-8             6222020               192.8 ns/op
BenchmarkBuildContext/depth_1/without
BenchmarkBuildContext/depth_1/without-8          5743065               182.9 ns/op
BenchmarkBuildContext/depth_5
BenchmarkBuildContext/depth_5/with
BenchmarkBuildContext/depth_5/with-8             6233917               184.8 ns/op
BenchmarkBuildContext/depth_5/without
BenchmarkBuildContext/depth_5/without-8          7289814               165.8 ns/op
BenchmarkBuildContext/depth_7
BenchmarkBuildContext/depth_7/with
BenchmarkBuildContext/depth_7/with-8             5941093               193.5 ns/op
BenchmarkBuildContext/depth_7/without
BenchmarkBuildContext/depth_7/without-8          7317411               167.6 ns/op
BenchmarkBuildContext/depth_10
BenchmarkBuildContext/depth_10/with
BenchmarkBuildContext/depth_10/with-8            5709080               207.0 ns/op
BenchmarkBuildContext/depth_10/without
BenchmarkBuildContext/depth_10/without-8                 7281186               168.9 ns/op

Change-Id: If38409916240dd15d4924505aa80f98c107830e4
Reviewed-on: https://go-review.googlesource.com/c/exp/+/325489
Trust: Jonathan Amsterdam <jba@google.com>
Run-TryBot: Jonathan Amsterdam <jba@google.com>
Reviewed-by: Ian Cottrell <iancottrell@google.com>
diff --git a/event/builder_test.go b/event/builder_test.go
index 4d3677a..418554e 100644
--- a/event/builder_test.go
+++ b/event/builder_test.go
@@ -128,3 +128,26 @@
 		b1.Log("msg2")
 	})
 }
+
+func BenchmarkBuildContext(b *testing.B) {
+	// How long does it take to deliver an event from a nested context?
+	for _, depth := range []int{1, 5, 7, 10} {
+		b.Run(fmt.Sprintf("depth %d", depth), func(b *testing.B) {
+			ctx := event.WithExporter(context.Background(), event.NewExporter(event.NopHandler{}, nil))
+			for i := 0; i < depth; i++ {
+				ctx = context.WithValue(ctx, i, i)
+			}
+			b.Run("direct", func(b *testing.B) {
+				for i := 0; i < b.N; i++ {
+					event.To(ctx).With(event.Name.Of("foo")).Metric()
+				}
+			})
+			b.Run("cloned", func(b *testing.B) {
+				bu := event.To(ctx)
+				for i := 0; i < b.N; i++ {
+					bu.Clone().With(event.Name.Of("foo")).Metric()
+				}
+			})
+		})
+	}
+}