diff --git a/rand/rand.go b/rand/rand.go new file mode 100644 index 0000000..a05da8e --- /dev/null +++ b/rand/rand.go @@ -0,0 +1,131 @@ +package rand + +import ( + "crypto/rand" + "io" + "sync" + "time" + + mrnd "math/rand" + + "github.com/charlienet/go-mixed/bytesconv" +) + +const ( + uppercase = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + lowercase = "abcdefghijklmnopqrstuvwxyz" + digit = "0123456789" + nomix = "BCDFGHJKMPQRTVWXY2346789" + letter = uppercase + lowercase + allChars = uppercase + lowercase + digit + hex = digit + "ABCDEF" + _ = allChars + "/+" +) + +type charScope struct { + bytes []byte + length int + max int + bits int + mask int + lenFunc func(int) int +} + +func StringScope(str string) *charScope { + return strScope(str, nil) +} + +func strScope(str string, f func(int) int) *charScope { + len := len(str) + + scope := &charScope{ + bytes: bytesconv.StringToBytes(str), + length: len, + lenFunc: f, + bits: 1, + } + + for scope.mask < len { + scope.bits++ + scope.mask = 1<= 0; { + if remain == 0 { + cache, remain = randInt63(), scope.max + } + + if idx := int(cache & int64(scope.mask)); idx < scope.length { + ret[i] = scope.bytes[idx] + i-- + } + + cache >>= int64(scope.bits) + remain-- + } + + return bytesconv.BytesToString(ret) +} + +// 获取指定范围内的随机数 +func RandInt(min, max int) int { + n := randNumber2(max - min) + return n + min +} + +// 生成指定范围的随机数 +func RandInt32(min, max int32) int32 { + return int32(RandInt(int(min), int(max))) +} + +func RandBytes(len int) ([]byte, error) { + r := make([]byte, len) + _, err := io.ReadFull(rand.Reader, r) + return r, err +} + +// func randNumber(max int64) (int64, error) { +// r, err := rand.Int(rand.Reader, big.NewInt(max+1)) +// return r.Int64(), err +// } + +func randInt63() int64 { + var v int64 + + randLock.Lock() + v = randSource.Int63() + randLock.Unlock() + + return v +} + +func randNumber2(max int) int { + rnd := mrnd.New(randSource) + return rnd.Intn(max) +} diff --git a/rand/rand_test.go b/rand/rand_test.go new file mode 100644 index 0000000..91bd3d3 --- /dev/null +++ b/rand/rand_test.go @@ -0,0 +1,118 @@ +package rand_test + +import ( + "bytes" + "testing" + "time" + + mrnd "math/rand" + + "github.com/charlienet/go-mixed/rand" +) + +func TestRandString(t *testing.T) { + t.Log(rand.AllChars.RandString(20)) + + // b, err := rand.RandBytes(32) + // t.Log(err) + // t.Log(hex.EncodeToString(b)) +} + +func TestRandHex(t *testing.T) { + h := rand.Hex.RandString(8) + t.Log(h) +} + +func TestRandMax(t *testing.T) { + mrnd.Seed(time.Now().UnixNano()) +} + +func BenchmarkParallel(b *testing.B) { + rand.Hex.RandString(16) + + b.RunParallel(func(pb *testing.PB) { + for pb.Next() { + rand.Hex.RandString(16) + } + }) +} + +func BenchmarkNoop(b *testing.B) { + for i := 0; i < b.N; i++ { + rand.AllChars.RandString(16) + } +} + +func BenchmarkRandString(b *testing.B) { + + for i := 0; i < 10; i++ { + rand.Hex.RandString(10) + } + + b.ResetTimer() + for i := 0; i < b.N; i++ { + rand.Hex.RandString(20) + } + + // b.Run("randString", func(b *testing.B) { + + // for i := 0; i < b.N; i++ { + // rand.Hex.RandString(256) + // } + // }) + + // for i := 0; i < b.N; i++ { + // rand.RandBytes(16) + // } +} + +func BenchmarkString(b *testing.B) { + elems := []byte("abcdefghijk") + + b.Run("1", func(b *testing.B) { + a := []byte{} + for i := 0; i < b.N; i++ { + for _, elem := range elems { + a = append(a, elem) + } + } + }) + + b.Run("2", func(b *testing.B) { + a := make([]byte, len(elems)) + for i := 0; i < b.N; i++ { + for _, elem := range elems { + a = append(a, elem) + } + } + }) + + b.Run("3", func(b *testing.B) { + a := make([]byte, len(elems)) + for i := 0; i < b.N; i++ { + a = append(a, elems...) + } + }) +} + +func BenchmarkConcatString(b *testing.B) { + elems := []string{"1", "2", "3", "4", "5"} + + b.Run("add", func(b *testing.B) { + for i := 0; i < b.N; i++ { + ret := "" + for _, elem := range elems { + ret += elem + } + } + }) + + b.Run("buffer", func(b *testing.B) { + for i := 0; i < b.N; i++ { + var buf bytes.Buffer + for _, elem := range elems { + buf.WriteString(elem) + } + } + }) +}