github.com/gogf/gf/v2@v2.7.4/util/grand/grand_buffer.go (about)

     1  // Copyright GoFrame Author(https://goframe.org). All Rights Reserved.
     2  //
     3  // This Source Code Form is subject to the terms of the MIT License.
     4  // If a copy of the MIT was not distributed with this file,
     5  // You can obtain one at https://github.com/gogf/gf.
     6  
     7  package grand
     8  
     9  import (
    10  	"crypto/rand"
    11  
    12  	"github.com/gogf/gf/v2/errors/gcode"
    13  	"github.com/gogf/gf/v2/errors/gerror"
    14  )
    15  
    16  const (
    17  	// Buffer size for uint32 random number.
    18  	bufferChanSize = 10000
    19  )
    20  
    21  var (
    22  	// bufferChan is the buffer for random bytes,
    23  	// every item storing 4 bytes.
    24  	bufferChan = make(chan []byte, bufferChanSize)
    25  )
    26  
    27  func init() {
    28  	go asyncProducingRandomBufferBytesLoop()
    29  }
    30  
    31  // asyncProducingRandomBufferBytes is a named goroutine, which uses an asynchronous goroutine
    32  // to produce the random bytes, and a buffer chan to store the random bytes.
    33  // So it has high performance to generate random numbers.
    34  func asyncProducingRandomBufferBytesLoop() {
    35  	var step int
    36  	for {
    37  		buffer := make([]byte, 1024)
    38  		if n, err := rand.Read(buffer); err != nil {
    39  			panic(gerror.WrapCode(gcode.CodeInternalError, err, `error reading random buffer from system`))
    40  		} else {
    41  			// The random buffer from system is very expensive,
    42  			// so fully reuse the random buffer by changing
    43  			// the step with a different number can
    44  			// improve the performance a lot.
    45  			// for _, step = range []int{4, 5, 6, 7} {
    46  			for _, step = range []int{4} {
    47  				for i := 0; i <= n-4; i += step {
    48  					bufferChan <- buffer[i : i+4]
    49  				}
    50  			}
    51  		}
    52  	}
    53  }