mirror of
https://gitee.com/johng/gf.git
synced 2024-11-30 03:07:45 +08:00
improve package guid
This commit is contained in:
parent
8e6f1f1740
commit
6889542801
@ -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))
|
||||
}
|
||||
}
|
||||
|
@ -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))
|
||||
}
|
||||
}
|
||||
|
@ -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))
|
||||
}
|
||||
|
@ -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))
|
||||
}
|
||||
|
@ -6,7 +6,7 @@
|
||||
|
||||
package gbinary
|
||||
|
||||
// 实验特性
|
||||
// NOTE: THIS IS AN EXPERIMENTAL FEATURE!
|
||||
|
||||
// 二进制位(0|1)
|
||||
type Bit int8
|
@ -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)
|
||||
|
@ -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()
|
||||
}
|
||||
|
@ -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]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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)
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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"))
|
||||
}
|
||||
}
|
||||
|
@ -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)
|
||||
})
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user