buffer_pool.go 2.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105
  1. // Copyright 2009 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. // +build go1.3
  5. package v1
  6. // Allocation pools for Buffers.
  7. import "sync"
  8. var pools [14]sync.Pool
  9. var pool64 *sync.Pool
  10. func init() {
  11. var i uint
  12. // TODO(pquerna): add science here around actual pool sizes.
  13. for i = 6; i < 20; i++ {
  14. n := 1 << i
  15. pools[poolNum(n)].New = func() interface{} { return make([]byte, 0, n) }
  16. }
  17. pool64 = &pools[0]
  18. }
  19. // This returns the pool number that will give a buffer of
  20. // at least 'i' bytes.
  21. func poolNum(i int) int {
  22. // TODO(pquerna): convert to log2 w/ bsr asm instruction:
  23. // <https://groups.google.com/forum/#!topic/golang-nuts/uAb5J1_y7ns>
  24. if i <= 64 {
  25. return 0
  26. } else if i <= 128 {
  27. return 1
  28. } else if i <= 256 {
  29. return 2
  30. } else if i <= 512 {
  31. return 3
  32. } else if i <= 1024 {
  33. return 4
  34. } else if i <= 2048 {
  35. return 5
  36. } else if i <= 4096 {
  37. return 6
  38. } else if i <= 8192 {
  39. return 7
  40. } else if i <= 16384 {
  41. return 8
  42. } else if i <= 32768 {
  43. return 9
  44. } else if i <= 65536 {
  45. return 10
  46. } else if i <= 131072 {
  47. return 11
  48. } else if i <= 262144 {
  49. return 12
  50. } else if i <= 524288 {
  51. return 13
  52. } else {
  53. return -1
  54. }
  55. }
  56. // Send a buffer to the Pool to reuse for other instances.
  57. // You may no longer utilize the content of the buffer, since it may be used
  58. // by other goroutines.
  59. func Pool(b []byte) {
  60. if b == nil {
  61. return
  62. }
  63. c := cap(b)
  64. // Our smallest buffer is 64 bytes, so we discard smaller buffers.
  65. if c < 64 {
  66. return
  67. }
  68. // We need to put the incoming buffer into the NEXT buffer,
  69. // since a buffer guarantees AT LEAST the number of bytes available
  70. // that is the top of this buffer.
  71. // That is the reason for dividing the cap by 2, so it gets into the NEXT bucket.
  72. // We add 2 to avoid rounding down if size is exactly power of 2.
  73. pn := poolNum((c + 2) >> 1)
  74. if pn != -1 {
  75. pools[pn].Put(b[0:0])
  76. }
  77. // if we didn't have a slot for this []byte, we just drop it and let the GC
  78. // take care of it.
  79. }
  80. // makeSlice allocates a slice of size n -- it will attempt to use a pool'ed
  81. // instance whenever possible.
  82. func makeSlice(n int) []byte {
  83. if n <= 64 {
  84. return pool64.Get().([]byte)[0:n]
  85. }
  86. pn := poolNum(n)
  87. if pn != -1 {
  88. return pools[pn].Get().([]byte)[0:n]
  89. } else {
  90. return make([]byte, n)
  91. }
  92. }