aboutsummaryrefslogtreecommitdiff
path: root/src/runtime/sema_test.go
diff options
context:
space:
mode:
Diffstat (limited to 'src/runtime/sema_test.go')
-rw-r--r--src/runtime/sema_test.go87
1 files changed, 55 insertions, 32 deletions
diff --git a/src/runtime/sema_test.go b/src/runtime/sema_test.go
index f3e95d10be..9943d2ed39 100644
--- a/src/runtime/sema_test.go
+++ b/src/runtime/sema_test.go
@@ -5,7 +5,7 @@
package runtime_test
import (
- "internal/testenv"
+ "fmt"
. "runtime"
"sync"
"sync/atomic"
@@ -103,45 +103,68 @@ func testSemaHandoff() bool {
return res == 1 // did the waiter run first?
}
-func TestSemTableOneAddrCollisionLinear(t *testing.T) {
- testenv.CheckLinear(t, func(scale float64) func(*testing.B) {
- n := int(1000 * scale)
- return func(b *testing.B) {
+func BenchmarkSemTable(b *testing.B) {
+ for _, n := range []int{1000, 2000, 4000, 8000} {
+ b.Run(fmt.Sprintf("OneAddrCollision/n=%d", n), func(b *testing.B) {
tab := Escape(new(SemTable))
u := make([]uint32, SemTableSize+1)
b.ResetTimer()
- // Simulate two locks colliding on the same semaRoot.
- //
- // Specifically enqueue all the waiters for the first lock,
- // then all the waiters for the second lock.
- //
- // Then, dequeue all the waiters from the first lock, then
- // the second.
- //
- // Each enqueue/dequeue operation should be O(1), because
- // there are exactly 2 locks. This could be O(n) if all
- // the waiters for both locks are on the same list, as it
- // once was.
- for i := 0; i < n; i++ {
- if i < n/2 {
- tab.Enqueue(&u[0])
- } else {
- tab.Enqueue(&u[SemTableSize])
+ for j := 0; j < b.N; j++ {
+ // Simulate two locks colliding on the same semaRoot.
+ //
+ // Specifically enqueue all the waiters for the first lock,
+ // then all the waiters for the second lock.
+ //
+ // Then, dequeue all the waiters from the first lock, then
+ // the second.
+ //
+ // Each enqueue/dequeue operation should be O(1), because
+ // there are exactly 2 locks. This could be O(n) if all
+ // the waiters for both locks are on the same list, as it
+ // once was.
+ for i := 0; i < n; i++ {
+ if i < n/2 {
+ tab.Enqueue(&u[0])
+ } else {
+ tab.Enqueue(&u[SemTableSize])
+ }
+ }
+ for i := 0; i < n; i++ {
+ var ok bool
+ if i < n/2 {
+ ok = tab.Dequeue(&u[0])
+ } else {
+ ok = tab.Dequeue(&u[SemTableSize])
+ }
+ if !ok {
+ b.Fatal("failed to dequeue")
+ }
}
}
- for i := 0; i < n; i++ {
- var ok bool
- if i < n/2 {
- ok = tab.Dequeue(&u[0])
- } else {
- ok = tab.Dequeue(&u[SemTableSize])
+ })
+ b.Run(fmt.Sprintf("ManyAddrCollision/n=%d", n), func(b *testing.B) {
+ tab := Escape(new(SemTable))
+ u := make([]uint32, n*SemTableSize)
+
+ b.ResetTimer()
+
+ for j := 0; j < b.N; j++ {
+ // Simulate n locks colliding on the same semaRoot.
+ //
+ // Each enqueue/dequeue operation should be O(log n), because
+ // each semaRoot is a tree. This could be O(n) if it was
+ // some simpler data structure.
+ for i := 0; i < n; i++ {
+ tab.Enqueue(&u[i*SemTableSize])
}
- if !ok {
- b.Fatal("failed to dequeue")
+ for i := 0; i < n; i++ {
+ if !tab.Dequeue(&u[i*SemTableSize]) {
+ b.Fatal("failed to dequeue")
+ }
}
}
- }
- })
+ })
+ }
}