improve package guid

This commit is contained in:
John 2020-05-27 11:26:05 +08:00
parent 8e6f1f1740
commit 6889542801
12 changed files with 86 additions and 77 deletions

View File

@ -10,4 +10,7 @@ func main() {
for i := 0; i < 100; i++ {
fmt.Println(grand.S(16))
}
for i := 0; i < 100; i++ {
fmt.Println(grand.N(0, 99999999))
}
}

View File

@ -6,5 +6,8 @@ import (
)
func main() {
fmt.Printf("TraceId: %s\n", guid.S())
for i := 0; i < 100; i++ {
s := guid.S()
fmt.Println(s, len(s))
}
}

View File

@ -7,9 +7,14 @@ import (
)
func main() {
fmt.Println(strconv.FormatUint(4589634556, 36))
fmt.Println(strconv.FormatUint(math.MaxUint64-2, 36))
fmt.Println(strconv.FormatUint(math.MaxUint32-1, 36))
fmt.Println(strconv.FormatUint(math.MaxUint32, 36))
fmt.Println(strconv.FormatUint(2000000, 36))
// 36*36^2+36*36+36
var s string
fmt.Println(strconv.ParseUint("zzz", 36, 3))
fmt.Println(1 << 1)
// MaxInt64
s = strconv.FormatUint(math.MaxUint64, 16)
fmt.Println(s, len(s))
// PID
s = strconv.FormatInt(1000000, 36)
fmt.Println(s, len(s))
}

View File

@ -6,17 +6,17 @@ import (
)
func main() {
for i := 0; i < 10; i++ {
for i := 0; i < 100; i++ {
s := guid.S([]byte("123"))
fmt.Println(s, len(s))
}
fmt.Println()
for i := 0; i < 10; i++ {
for i := 0; i < 100; i++ {
s := guid.S([]byte("123"), []byte("456"))
fmt.Println(s, len(s))
}
fmt.Println()
for i := 0; i < 10; i++ {
for i := 0; i < 100; i++ {
s := guid.S([]byte("123"), []byte("456"), []byte("789"))
fmt.Println(s, len(s))
}

View File

@ -6,7 +6,7 @@
package gbinary
// 实验特性
// NOTE: THIS IS AN EXPERIMENTAL FEATURE!
// 二进制位(0|1)
type Bit int8

View File

@ -9,6 +9,7 @@ package ghttp
import (
"context"
"fmt"
"github.com/gogf/gf/internal/intlog"
"github.com/gogf/gf/os/gres"
"github.com/gogf/gf/os/gsession"
"github.com/gogf/gf/os/gview"
@ -79,12 +80,11 @@ func newRequest(s *Server, r *http.Request, w http.ResponseWriter) *Request {
// Custom session id creating function.
err := request.Session.SetIdFunc(func(ttl time.Duration) string {
var (
agent = request.UserAgent()
address = request.RemoteAddr
cookie = request.Header.Get("Cookie")
header = fmt.Sprintf("%v", request.Header)
)
//intlog.Print(agent, address, cookie)
return guid.S([]byte(agent), []byte(address), []byte(cookie))
intlog.Print(address, header)
return guid.S([]byte(address), []byte(header))
})
if err != nil {
panic(err)

View File

@ -12,25 +12,25 @@ import (
"github.com/gogf/gf/os/gtime"
)
func Benchmark_Second(b *testing.B) {
func Benchmark_Timestamp(b *testing.B) {
for i := 0; i < b.N; i++ {
gtime.Timestamp()
}
}
func Benchmark_Millisecond(b *testing.B) {
func Benchmark_TimestampMilli(b *testing.B) {
for i := 0; i < b.N; i++ {
gtime.TimestampMilli()
}
}
func Benchmark_Microsecond(b *testing.B) {
func Benchmark_TimestampMicro(b *testing.B) {
for i := 0; i < b.N; i++ {
gtime.TimestampMicro()
}
}
func Benchmark_Nanosecond(b *testing.B) {
func Benchmark_TimestampNano(b *testing.B) {
for i := 0; i < b.N; i++ {
gtime.TimestampNano()
}

View File

@ -37,23 +37,12 @@ func asyncProducingRandomBufferBytesLoop() {
} else {
// The random buffer from system is very expensive,
// so fully reuse the random buffer by changing
// the step with a different prime number can
// the step with a different number can
// improve the performance a lot.
step = 4
for i := 0; i < n-4; i += step {
bufferChan <- buffer[i : i+4]
}
step = 5
for i := 0; i < n-4; i += step {
bufferChan <- buffer[i : i+4]
}
step = 7
for i := 0; i < n-4; i += step {
bufferChan <- buffer[i : i+4]
}
step = 13
for i := 0; i < n-4; i += step {
bufferChan <- buffer[i : i+4]
for _, step = range []int{4, 5, 6, 7} {
for i := 0; i <= n-4; i += step {
bufferChan <- buffer[i : i+4]
}
}
}
}

View File

@ -17,11 +17,25 @@ import (
)
var (
buffer = make([]byte, 8)
strForStr = "我爱GoFrame"
buffer = make([]byte, 8)
randBuffer4 = make([]byte, 4)
randBuffer1024 = make([]byte, 1024)
strForStr = "我爱GoFrame"
)
func Benchmark_Rand_Intn(b *testing.B) {
func Benchmark_Rand_Buffer4(b *testing.B) {
for i := 0; i < b.N; i++ {
rand.Read(randBuffer4)
}
}
func Benchmark_Rand_Buffer1024(b *testing.B) {
for i := 0; i < b.N; i++ {
rand.Read(randBuffer1024)
}
}
func Benchmark_GRand_Intn(b *testing.B) {
for i := 0; i < b.N; i++ {
grand.N(0, 99)
}

View File

@ -25,7 +25,7 @@ import (
var (
sequence gtype.Uint32 // Sequence for unique purpose of current process.
sequenceMax = uint32(1000000) // Sequence max.
sequenceMax = uint32(46655) // Sequence max("zzz").
randomStrBase = "0123456789abcdefghijklmnopqrstuvwxyz" // Random chars string(36 bytes).
macAddrStr = "0000000" // MAC addresses hash result in 7 bytes.
processIdStr = "0000" // Process id in 4 bytes.
@ -42,47 +42,47 @@ func init() {
}
b := []byte{'0', '0', '0', '0', '0', '0', '0'}
s := strconv.FormatUint(uint64(ghash.DJBHash(macAddrBytes)), 36)
copy(b[7-len(s):], s)
copy(b, s)
macAddrStr = string(b)
}
// Process id in 4 bytes.
{
b := []byte{'0', '0', '0', '0'}
s := strconv.FormatInt(int64(os.Getpid()), 36)
copy(b[4-len(s):], s)
copy(b, s)
processIdStr = string(b)
}
}
// S creates and returns an unique string in 36 bytes that meets most common usages
// without strict UUID algorithm. It returns an unique string using default unique
// algorithm if no <data> is given.
// S creates and returns a global unique string in 32 bytes that meets most common
// usages without strict UUID algorithm. It returns an unique string using default
// unique algorithm if no <data> is given.
//
// The specified <data> can be no more than 3 count. No matter how long each of the <data>
// size is, each of them will be hashed into 7 bytes as part of the result. If given
// <data> count is less than 3, the leftover size of the result bytes will be token by
// random string.
// The specified <data> can be no more than 2 count. No matter how long each of the
// <data> size is, each of them will be hashed into 7 bytes as part of the result.
// If given <data> count is less than 2, the leftover size of the result bytes will
// be token by random string.
//
// The returned string is composed with:
// 1. Default: MAC(7) + PID(4) + Sequence(4) + TimestampNano(12) + RandomString(9)
// 2. CustomData: Data...(7 - 21) + TimestampNano(12) + RandomString(3 - 17)
// 1. Default: MAC(7) + PID(4) + TimestampNano(12) + Sequence(3) + RandomString(6)
// 2. CustomData: Data(7/14) + TimestampNano(12) + Sequence(3) + RandomString(3/10)
//
// Note that
// 1. The returned length is fixed to 36 bytes for performance purpose.
// 1. The returned length is fixed to 32 bytes for performance purpose.
// 2. The custom parameter <data> composed should have unique attribute in your
// business situation.
func S(data ...[]byte) string {
var (
b = make([]byte, 36)
b = make([]byte, 32)
nanoStr = strconv.FormatInt(time.Now().UnixNano(), 36)
)
if len(data) == 0 {
copy(b, macAddrStr)
copy(b[7:], processIdStr)
copy(b[11:], getSequence())
copy(b[15:], nanoStr)
copy(b[27:], getRandomStr(9))
} else if len(data) <= 3 {
copy(b[11:], nanoStr)
copy(b[23:], getSequence())
copy(b[26:], getRandomStr(6))
} else if len(data) <= 2 {
n := 0
for i, v := range data {
// Ignore empty data item bytes.
@ -92,26 +92,27 @@ func S(data ...[]byte) string {
}
}
copy(b[n:], nanoStr)
copy(b[n+12:], getRandomStr(36-n-12))
copy(b[n+12:], getSequence())
copy(b[n+12+3:], getRandomStr(32-n-12-3))
} else {
panic("data count too long, no more than 3")
panic("data count too long, no more than 2")
}
return gconv.UnsafeBytesToStr(b)
}
// getSequence increases and returns the sequence string in 4 bytes.
// The sequence is less than 1000000.
func getSequence() string {
b := []byte{'0', '0', '0', '0'}
// getSequence increases and returns the sequence string in 3 bytes.
// The sequence is less than "zzz"(46655).
func getSequence() []byte {
b := []byte{'0', '0', '0'}
s := strconv.FormatUint(uint64(sequence.Add(1)%sequenceMax), 36)
copy(b[4-len(s):], s)
return gconv.UnsafeBytesToStr(b)
copy(b, s)
return b
}
// getRandomStr randomly picks and returns <n> count of chars from randomStrBase.
func getRandomStr(n int) string {
func getRandomStr(n int) []byte {
if n <= 0 {
return ""
return []byte{}
}
var (
b = make([]byte, n)
@ -120,13 +121,13 @@ func getRandomStr(n int) string {
for i := range b {
b[i] = randomStrBase[numberBytes[i]%36]
}
return gconv.UnsafeBytesToStr(b)
return b
}
// getDataHashStr creates and returns hash bytes in 7 bytes with given data bytes.
func getDataHashStr(data []byte) string {
func getDataHashStr(data []byte) []byte {
b := []byte{'0', '0', '0', '0', '0', '0', '0'}
s := strconv.FormatUint(uint64(ghash.DJBHash(data)), 36)
copy(b[7-len(s):], s)
return gconv.UnsafeBytesToStr(b)
copy(b, s)
return b
}

View File

@ -30,9 +30,3 @@ func Benchmark_S_Data_2(b *testing.B) {
guid.S([]byte("123"), []byte("456"))
}
}
func Benchmark_S_Data_3(b *testing.B) {
for i := 0; i < b.N; i++ {
guid.S([]byte("123"), []byte("456"), []byte("789"))
}
}

View File

@ -22,13 +22,13 @@ func Test_S(t *testing.T) {
for i := 0; i < 1000000; i++ {
s := guid.S()
t.Assert(set.AddIfNotExist(s), true)
t.Assert(len(s), 36)
t.Assert(len(s), 32)
}
})
}
func Test_S_Data(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
t.Assert(len(guid.S([]byte("123"))), 36)
t.Assert(len(guid.S([]byte("123"))), 32)
})
}