改进grand随机数生成设计,底层使用crypto/rand+缓冲区实现高速的随机数生成;gtime模块增加FuncCost函数执行耗时计算

This commit is contained in:
john
2018-11-05 13:53:17 +08:00
parent 1f5834d94c
commit d257e554dd
9 changed files with 154 additions and 18 deletions

View File

@ -26,7 +26,7 @@ type Session struct {
server *Server // 所属Server
}
// 生成一个唯一的sessionid字符串
// 生成一个唯一的sessionid字符串长度16
func makeSessionId() string {
return strings.ToUpper(strconv.FormatInt(gtime.Nanosecond(), 32) + grand.RandStr(3))
}

View File

@ -306,4 +306,11 @@ func ParseTimeFromContent(content string, format...string) *Time {
}
}
return nil
}
// 计算函数f执行的时间单位纳秒
func FuncCost(f func()) int64 {
t := Nanosecond()
f()
return Nanosecond() - t
}

View File

@ -15,7 +15,7 @@ import (
"strings"
)
// 将变量i转换为字符串指定的类型t非必须参数extraParams泳衣额外的参数传递
// 将变量i转换为字符串指定的类型t非必须参数extraParams用以额外的参数传递
func Convert(i interface{}, t string, extraParams...interface{}) interface{} {
switch t {
case "int": return Int(i)

View File

@ -7,18 +7,9 @@
// 随机数管理
package grand
import (
"time"
)
var letters = []rune("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789")
var digits = []rune("0123456789")
// 自定义的 rand.Intn
func intn (max int) int {
return int(time.Now().UnixNano())%max
}
// 获得一个 min, max 之间的随机数(min <= x <= max)
func Rand (min, max int) int {
if min >= max {

View File

@ -0,0 +1,45 @@
// Copyright 2018 gf Author(https://gitee.com/johng/gf). All Rights Reserved.
//
// This Source Code Form is subject to the terms of the MIT License.
// If a copy of the MIT was not distributed with this file,
// You can obtain one at https://gitee.com/johng/gf.
package grand
import (
"crypto/rand"
"encoding/binary"
)
const (
gBUFFER_SIZE = 10000 // 缓冲区uint64数量大小
)
var (
bufferChan = make(chan uint64, gBUFFER_SIZE)
)
// 使用缓冲区实现快速的随机数生成
func init() {
buffer := make([]byte, 1024)
go func() {
for {
if n, err := rand.Read(buffer); err != nil {
panic(err)
} else {
for i := 0; i < n - 8; i += 8 {
bufferChan <- binary.LittleEndian.Uint64(buffer[i : i + 8])
}
}
}
}()
}
// 自定义的 rand.Intn ,绝对随机
func intn (max int) int {
n := int(<- bufferChan)%max
if n < 0 {
return -n
}
return n
}

View File

@ -15,6 +15,6 @@ import (
func Benchmark_Rand(b *testing.B) {
for i := 0; i < b.N; i++ {
grand.Rand(0, 200)
grand.Rand(0, 999999999)
}
}

View File

@ -3,13 +3,11 @@ package main
import (
"fmt"
"gitee.com/johng/gf/g/os/gtime"
"strconv"
)
func main() {
s := `
[INFO] 2018-11-04 12:48:01 2018-11-04 12:48:01 ["handle eventMedlinker\\Med3Svr\\App\\Events\\Task\\InviteUserVerifyEvent::__set_state(array(\n 'deviceNum' => '25a715ff8d4835197299d7dab067841e',\n 'userIdList' => \n array (\n 0 => '62506063',\n ),\n 'dataId' => '',\n 'eventTime' => NULL,\n))"] [med3-svr-6c8c9b9f4f-fl6g9]
`
t := gtime.ParseTimeFromContent(s)
fmt.Println(t.String())
fmt.Println(strconv.FormatInt(gtime.Nanosecond(), 32))
fmt.Println(gtime.Second())
fmt.Println(gtime.Nanosecond())
}

12
geg/util/grand/grand.go Normal file
View File

@ -0,0 +1,12 @@
package main
import (
"fmt"
"gitee.com/johng/gf/g/util/grand"
)
func main() {
for i := 0; i < 10; i++ {
fmt.Println(grand.Rand(0, 99999))
}
}

83
geg/util/grand/rand.go Normal file
View File

@ -0,0 +1,83 @@
package main
import (
crand "crypto/rand"
"encoding/binary"
"fmt"
"gitee.com/johng/gf/g/os/gtime"
mrand "math/rand"
"os"
"time"
)
// int 随机
func a1() {
s1 := mrand.NewSource(time.Now().UnixNano())
r1 := mrand.New(s1)
for i := 0; i < 10; i++ {
fmt.Printf("%d ", r1.Intn(100))
}
fmt.Printf("\n")
}
// 0/1 true/false 随机
func a2() {
// Go编程这本书上例子.
ch := make(chan int, 1)
for i := 0; i < 10; i++ {
select {
case ch <- 0:
case ch <- 1:
}
r := <-ch
fmt.Printf("%d ", r)
}
fmt.Printf("\n")
}
//真随机 -- 用标准库封装好的
func a3() {
b := make([]byte, 16)
// On Unix-like systems, Reader reads from /dev/urandom.
// On Windows systems, Reader uses the CryptGenRandom API.
_, err := crand.Read(b) //返回长度为0 - 32 的值
if err != nil {
fmt.Println("[a3] ", err)
return
}
fmt.Println("[a3] b:", b)
}
//真随机 -- 我们直接调真随机文件生成了事。 但注意,它是阻塞式的。
func a4() {
f, err := os.Open("/dev/random")
if err != nil {
fmt.Println("[a4] ", err)
return
}
defer f.Close()
b1 := make([]byte, 16)
_, err = f.Read(b1)
if err != nil {
fmt.Println("[a4] ", err)
return
}
fmt.Println("[a4] Read /dev/random:", b1)
}
// a3 的另一种实现方式
func a5() {
var ret int32
binary.Read(crand.Reader, binary.LittleEndian, &ret)
fmt.Println("[a5] ret:", ret)
}
func main() {
fmt.Println("a1:", gtime.FuncCost(a1))
fmt.Println("a2:", gtime.FuncCost(a2))
fmt.Println("a3:", gtime.FuncCost(a3))
fmt.Println("a4:", gtime.FuncCost(a4))
fmt.Println("a5:", gtime.FuncCost(a5))
}