pool_test.go 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165
  1. // Copyright 2013 The Go Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style
  3. // license that can be found in the LICENSE file.
  4. // Pool is no-op under race detector, so all these tests do not work.
  5. // +build !race
  6. package sync_test
  7. import (
  8. "runtime"
  9. "runtime/debug"
  10. . "sync"
  11. "sync/atomic"
  12. "testing"
  13. "time"
  14. )
  15. func TestPool(t *testing.T) {
  16. // disable GC so we can control when it happens.
  17. defer debug.SetGCPercent(debug.SetGCPercent(-1))
  18. var p Pool
  19. if p.Get() != nil {
  20. t.Fatal("expected empty")
  21. }
  22. p.Put("a")
  23. p.Put("b")
  24. if g := p.Get(); g != "a" {
  25. t.Fatalf("got %#v; want a", g)
  26. }
  27. if g := p.Get(); g != "b" {
  28. t.Fatalf("got %#v; want b", g)
  29. }
  30. if g := p.Get(); g != nil {
  31. t.Fatalf("got %#v; want nil", g)
  32. }
  33. p.Put("c")
  34. debug.SetGCPercent(100) // to allow following GC to actually run
  35. runtime.GC()
  36. if g := p.Get(); g != nil {
  37. t.Fatalf("got %#v; want nil after GC", g)
  38. }
  39. }
  40. func TestPoolNew(t *testing.T) {
  41. // disable GC so we can control when it happens.
  42. defer debug.SetGCPercent(debug.SetGCPercent(-1))
  43. i := 0
  44. p := Pool{
  45. New: func() interface{} {
  46. i++
  47. return i
  48. },
  49. }
  50. if v := p.Get(); v != 1 {
  51. t.Fatalf("got %v; want 1", v)
  52. }
  53. if v := p.Get(); v != 2 {
  54. t.Fatalf("got %v; want 2", v)
  55. }
  56. p.Put(42)
  57. if v := p.Get(); v != 42 {
  58. t.Fatalf("got %v; want 42", v)
  59. }
  60. if v := p.Get(); v != 3 {
  61. t.Fatalf("got %v; want 3", v)
  62. }
  63. }
  64. // Test that Pool does not hold pointers to previously cached resources.
  65. func TestPoolGC(t *testing.T) {
  66. testPool(t, true)
  67. }
  68. // Test that Pool releases resources on GC.
  69. func TestPoolRelease(t *testing.T) {
  70. testPool(t, false)
  71. }
  72. func testPool(t *testing.T, drain bool) {
  73. t.Skip("gccgo imprecise GC breaks this test")
  74. var p Pool
  75. const N = 100
  76. loop:
  77. for try := 0; try < 3; try++ {
  78. var fin, fin1 uint32
  79. for i := 0; i < N; i++ {
  80. v := new(string)
  81. runtime.SetFinalizer(v, func(vv *string) {
  82. atomic.AddUint32(&fin, 1)
  83. })
  84. p.Put(v)
  85. }
  86. if drain {
  87. for i := 0; i < N; i++ {
  88. p.Get()
  89. }
  90. }
  91. for i := 0; i < 5; i++ {
  92. runtime.GC()
  93. time.Sleep(time.Duration(i*100+10) * time.Millisecond)
  94. // 1 pointer can remain on stack or elsewhere
  95. if fin1 = atomic.LoadUint32(&fin); fin1 >= N-1 {
  96. continue loop
  97. }
  98. }
  99. t.Fatalf("only %v out of %v resources are finalized on try %v", fin1, N, try)
  100. }
  101. }
  102. func TestPoolStress(t *testing.T) {
  103. const P = 10
  104. N := int(1e6)
  105. if testing.Short() {
  106. N /= 100
  107. }
  108. var p Pool
  109. done := make(chan bool)
  110. for i := 0; i < P; i++ {
  111. go func() {
  112. var v interface{} = 0
  113. for j := 0; j < N; j++ {
  114. if v == nil {
  115. v = 0
  116. }
  117. p.Put(v)
  118. v = p.Get()
  119. if v != nil && v.(int) != 0 {
  120. t.Fatalf("expect 0, got %v", v)
  121. }
  122. }
  123. done <- true
  124. }()
  125. }
  126. for i := 0; i < P; i++ {
  127. <-done
  128. }
  129. }
  130. func BenchmarkPool(b *testing.B) {
  131. var p Pool
  132. b.RunParallel(func(pb *testing.PB) {
  133. for pb.Next() {
  134. p.Put(1)
  135. p.Get()
  136. }
  137. })
  138. }
  139. func BenchmarkPoolOverflow(b *testing.B) {
  140. var p Pool
  141. b.RunParallel(func(pb *testing.PB) {
  142. for pb.Next() {
  143. for b := 0; b < 100; b++ {
  144. p.Put(1)
  145. }
  146. for b := 0; b < 100; b++ {
  147. p.Get()
  148. }
  149. }
  150. })
  151. }