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