grand_buffer.go 1.5 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253
  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. package grand
  7. import (
  8. "crypto/rand"
  9. "github.com/gogf/gf/v2/errors/gcode"
  10. "github.com/gogf/gf/v2/errors/gerror"
  11. )
  12. const (
  13. // Buffer size for uint32 random number.
  14. bufferChanSize = 10000
  15. )
  16. var (
  17. // bufferChan is the buffer for random bytes,
  18. // every item storing 4 bytes.
  19. bufferChan = make(chan []byte, bufferChanSize)
  20. )
  21. func init() {
  22. go asyncProducingRandomBufferBytesLoop()
  23. }
  24. // asyncProducingRandomBufferBytes is a named goroutine, which uses an asynchronous goroutine
  25. // to produce the random bytes, and a buffer chan to store the random bytes.
  26. // So it has high performance to generate random numbers.
  27. func asyncProducingRandomBufferBytesLoop() {
  28. var step int
  29. for {
  30. buffer := make([]byte, 1024)
  31. if n, err := rand.Read(buffer); err != nil {
  32. panic(gerror.WrapCode(gcode.CodeInternalError, err, `error reading random buffer from system`))
  33. } else {
  34. // The random buffer from system is very expensive,
  35. // so fully reuse the random buffer by changing
  36. // the step with a different number can
  37. // improve the performance a lot.
  38. // for _, step = range []int{4, 5, 6, 7} {
  39. for _, step = range []int{4} {
  40. for i := 0; i <= n-4; i += step {
  41. bufferChan <- buffer[i : i+4]
  42. }
  43. }
  44. }
  45. }
  46. }