From 3dba31942f46230cdf2270bad32afea72ffbe3cc Mon Sep 17 00:00:00 2001 From: ideaa Date: Fri, 5 Sep 2025 18:01:02 +0800 Subject: [PATCH] simple uid --- utils/uidgen/simple_uid.go | 36 ++ utils/uidgen/simple_uid_test.go | 980 ++++++++++++++++++++++++++++++++ 2 files changed, 1016 insertions(+) create mode 100644 utils/uidgen/simple_uid.go create mode 100644 utils/uidgen/simple_uid_test.go diff --git a/utils/uidgen/simple_uid.go b/utils/uidgen/simple_uid.go new file mode 100644 index 0000000..fb8b3e9 --- /dev/null +++ b/utils/uidgen/simple_uid.go @@ -0,0 +1,36 @@ +package uidgen + +import ( + "fmt" + "strconv" + "sync/atomic" + "time" +) + +// 全局原子计数器 +var counter uint64 + +// GenId 并发安全的生成 16 位整型ID +func GenId() int64 { + idStr := GenSid() + id, _ := strconv.ParseInt(idStr, 10, 64) + return id +} + +// GenSid 并发安全的生成 16 位字符串ID +func GenSid() string { + now := time.Now() + yearPart := 100 + (now.Year() - 2025) + dayPart := now.YearDay() + 521 + secsOfDay := now.Hour()*3600 + now.Minute()*60 + now.Second() + + subSecondPart := now.Nanosecond() / 1e5 + base := uint64(secsOfDay)*100000 + uint64(subSecondPart) + seq := atomic.AddUint64(&counter, 1) + if seq < base { + atomic.CompareAndSwapUint64(&counter, seq, base) + seq = base + } + + return fmt.Sprintf("%03d%03d%010d", yearPart, dayPart, seq) +} diff --git a/utils/uidgen/simple_uid_test.go b/utils/uidgen/simple_uid_test.go new file mode 100644 index 0000000..e396690 --- /dev/null +++ b/utils/uidgen/simple_uid_test.go @@ -0,0 +1,980 @@ +package uidgen + +import ( + "log" + "math/rand" + "runtime" + "sync" + "testing" + "time" + + "github.com/spf13/cast" +) + +func TestGenerateID(t *testing.T) { + ddd := map[int64]bool{} + + for i := 0; i < 800000; i++ { + tid := GenId() + lll := len(cast.ToString(tid)) + if ddd[tid] || lll != 16 { + t.Errorf("测试失败") + log.Println(tid, " -- ", len(cast.ToString(tid))) + } else { + ddd[tid] = true + } + } + + log.Println(len(ddd)) +} + +func TestConcurrentGenId(t *testing.T) { + const goroutines = 1000 + const iterations = 100 + + results := make(chan int64, goroutines*iterations) + var wg sync.WaitGroup + + log.Printf("开始高并发测试: %d个goroutine,每个生成%d个ID\n", goroutines, iterations) + start := time.Now() + + // 真正的高并发测试 + for i := 0; i < goroutines; i++ { + wg.Add(1) + go func() { + defer wg.Done() + for j := 0; j < iterations; j++ { + results <- GenId() + // 不要sleep,保持真正的并发压力 + } + }() + } + + wg.Wait() + close(results) + + duration := time.Since(start) + log.Printf("生成完成,耗时: %v\n", duration) + + // 检查重复和长度 + seen := make(map[int64]bool) + duplicates := 0 + invalidLength := 0 + total := 0 + + for id := range results { + total++ + if seen[id] { + duplicates++ + t.Errorf("发现重复ID: %d", id) + } + seen[id] = true + + idStr := cast.ToString(id) + if len(idStr) != 16 { + invalidLength++ + t.Errorf("ID长度不正确: %d (长度: %d)", id, len(idStr)) + } + } + + log.Printf("测试结果统计:\n") + log.Printf("- 总生成数量: %d\n", total) + log.Printf("- 唯一ID数量: %d\n", len(seen)) + log.Printf("- 重复ID数量: %d\n", duplicates) + log.Printf("- 长度错误数量: %d\n", invalidLength) + log.Printf("- 生成速率: %.2f ID/秒\n", float64(total)/duration.Seconds()) + + if duplicates > 0 { + t.Fatalf("发现 %d 个重复ID,测试失败!", duplicates) + } + + if invalidLength > 0 { + t.Fatalf("发现 %d 个长度错误的ID,测试失败!", invalidLength) + } +} + +// 跨秒边界测试 +func TestCrossSecondBoundary(t *testing.T) { + log.Println("开始跨秒边界测试...") + + // 等待接近下一秒 + now := time.Now() + nextSecond := now.Truncate(time.Second).Add(time.Second) + time.Sleep(time.Until(nextSecond.Add(-100 * time.Millisecond))) + + const goroutines = 500 + results := make(chan int64, goroutines) + var wg sync.WaitGroup + + // 在秒边界附近启动大量goroutine + for i := 0; i < goroutines; i++ { + wg.Add(1) + go func() { + defer wg.Done() + results <- GenId() + }() + } + + wg.Wait() + close(results) + + // 检查重复 + seen := make(map[int64]bool) + duplicates := 0 + total := 0 + + for id := range results { + total++ + if seen[id] { + duplicates++ + t.Errorf("跨秒边界测试发现重复ID: %d", id) + } + seen[id] = true + } + + log.Printf("跨秒边界测试结果: 总数=%d, 唯一=%d, 重复=%d\n", total, len(seen), duplicates) + + if duplicates > 0 { + t.Fatalf("跨秒边界测试发现 %d 个重复ID!", duplicates) + } +} + +// 极限压力测试 +func TestExtremeStress(t *testing.T) { + const goroutines = 5000 + const iterations = 200 + + log.Printf("开始极限压力测试: %d个goroutine,每个生成%d个ID\n", goroutines, iterations) + start := time.Now() + + results := make(chan int64, goroutines*iterations) + var wg sync.WaitGroup + + for i := 0; i < goroutines; i++ { + wg.Add(1) + go func() { + defer wg.Done() + for j := 0; j < iterations; j++ { + results <- GenId() + } + }() + } + + wg.Wait() + close(results) + + duration := time.Since(start) + log.Printf("极限压力测试完成,耗时: %v\n", duration) + + // 检查重复 + seen := make(map[int64]bool) + duplicates := 0 + total := 0 + + for id := range results { + total++ + if seen[id] { + duplicates++ + t.Errorf("极限压力测试发现重复ID: %d", id) + } + seen[id] = true + } + + log.Printf("极限压力测试结果: 总数=%d, 唯一=%d, 重复=%d, 速率=%.2f ID/秒\n", + total, len(seen), duplicates, float64(total)/duration.Seconds()) + + if duplicates > 0 { + t.Fatalf("极限压力测试发现 %d 个重复ID!", duplicates) + } +} + +// 同一毫秒内的超高并发测试 +func TestSameMillisecondConcurrency(t *testing.T) { + log.Println("开始同一毫秒内超高并发测试...") + + const goroutines = 10000 + results := make(chan int64, goroutines) + var wg sync.WaitGroup + var startSignal sync.WaitGroup + startSignal.Add(1) + + // 预先启动所有goroutine,等待信号同时开始 + for i := 0; i < goroutines; i++ { + wg.Add(1) + go func() { + defer wg.Done() + startSignal.Wait() // 等待开始信号 + results <- GenId() + }() + } + + // 短暂延迟后同时释放所有goroutine + time.Sleep(10 * time.Millisecond) + startSignal.Done() + + wg.Wait() + close(results) + + // 检查重复 + seen := make(map[int64]bool) + duplicates := 0 + total := 0 + + for id := range results { + total++ + if seen[id] { + duplicates++ + t.Errorf("同一毫秒测试发现重复ID: %d", id) + } + seen[id] = true + } + + log.Printf("同一毫秒测试结果: 总数=%d, 唯一=%d, 重复=%d\n", total, len(seen), duplicates) + + if duplicates > 0 { + t.Fatalf("同一毫秒测试发现 %d 个重复ID!", duplicates) + } +} + +// 超极限压力测试 - 挑战单秒10万次限制 +func TestUltraExtremeStress(t *testing.T) { + const goroutines = 20000 + const iterations = 10 + + log.Printf("开始超极限压力测试: %d个goroutine,每个生成%d个ID (总计%d个)\n", + goroutines, iterations, goroutines*iterations) + start := time.Now() + + results := make(chan int64, goroutines*iterations) + var wg sync.WaitGroup + var startSignal sync.WaitGroup + startSignal.Add(1) + + // 预先启动所有goroutine,等待信号同时开始 + for i := 0; i < goroutines; i++ { + wg.Add(1) + go func() { + defer wg.Done() + startSignal.Wait() // 等待开始信号 + for j := 0; j < iterations; j++ { + results <- GenId() + } + }() + } + + // 同时释放所有goroutine,制造极端并发 + startSignal.Done() + + wg.Wait() + close(results) + + duration := time.Since(start) + log.Printf("超极限压力测试完成,耗时: %v\n", duration) + + // 检查重复 + seen := make(map[int64]bool) + duplicates := 0 + total := 0 + duplicateIds := make([]int64, 0) + + for id := range results { + total++ + if seen[id] { + duplicates++ + duplicateIds = append(duplicateIds, id) + t.Errorf("超极限压力测试发现重复ID: %d", id) + } + seen[id] = true + } + + log.Printf("超极限压力测试结果: 总数=%d, 唯一=%d, 重复=%d, 速率=%.2f ID/秒\n", + total, len(seen), duplicates, float64(total)/duration.Seconds()) + + if len(duplicateIds) > 0 { + log.Printf("重复的ID列表: %v\n", duplicateIds[:min(len(duplicateIds), 10)]) + } + + if duplicates > 0 { + t.Fatalf("超极限压力测试发现 %d 个重复ID!", duplicates) + } +} + +// 连续秒边界冲击测试 +func TestContinuousSecondBoundaryStress(t *testing.T) { + log.Println("开始连续秒边界冲击测试...") + + const rounds = 5 + const goroutinesPerRound = 5000 + allResults := make([]int64, 0, rounds*goroutinesPerRound) + var mu sync.Mutex + + for round := 0; round < rounds; round++ { + log.Printf("第 %d 轮秒边界测试\n", round+1) + + // 等待接近下一秒 + now := time.Now() + nextSecond := now.Truncate(time.Second).Add(time.Second) + time.Sleep(time.Until(nextSecond.Add(-50 * time.Millisecond))) + + results := make(chan int64, goroutinesPerRound) + var wg sync.WaitGroup + var startSignal sync.WaitGroup + startSignal.Add(1) + + // 在秒边界附近启动大量goroutine + for i := 0; i < goroutinesPerRound; i++ { + wg.Add(1) + go func() { + defer wg.Done() + startSignal.Wait() + results <- GenId() + }() + } + + startSignal.Done() + wg.Wait() + close(results) + + // 收集结果 + mu.Lock() + for id := range results { + allResults = append(allResults, id) + } + mu.Unlock() + } + + // 检查所有轮次的重复 + seen := make(map[int64]bool) + duplicates := 0 + duplicateIds := make([]int64, 0) + + for _, id := range allResults { + if seen[id] { + duplicates++ + duplicateIds = append(duplicateIds, id) + t.Errorf("连续秒边界测试发现重复ID: %d", id) + } + seen[id] = true + } + + log.Printf("连续秒边界测试结果: 总数=%d, 唯一=%d, 重复=%d\n", + len(allResults), len(seen), duplicates) + + if len(duplicateIds) > 0 { + log.Printf("重复的ID列表: %v\n", duplicateIds[:min(len(duplicateIds), 10)]) + } + + if duplicates > 0 { + t.Fatalf("连续秒边界测试发现 %d 个重复ID!", duplicates) + } +} + +// 长时间持续压力测试 +func TestLongRunningStress(t *testing.T) { + if testing.Short() { + t.Skip("跳过长时间测试") + } + + log.Println("开始长时间持续压力测试 (5秒)...") + + const duration = 5 * time.Second + const goroutines = 1000 + + results := make(chan int64, 1000000) // 预分配大缓冲区 + var wg sync.WaitGroup + stop := make(chan struct{}) + + start := time.Now() + + // 启动持续生成ID的goroutine + for i := 0; i < goroutines; i++ { + wg.Add(1) + go func() { + defer wg.Done() + for { + select { + case <-stop: + return + case results <- GenId(): + time.Sleep(time.Microsecond) // 微小延迟避免CPU占用过高 + } + } + }() + } + + // 运行指定时间后停止 + time.Sleep(duration) + close(stop) + wg.Wait() + close(results) + + actualDuration := time.Since(start) + log.Printf("长时间测试完成,实际耗时: %v\n", actualDuration) + + // 检查重复 + seen := make(map[int64]bool) + duplicates := 0 + total := 0 + duplicateIds := make([]int64, 0) + + for id := range results { + total++ + if seen[id] { + duplicates++ + duplicateIds = append(duplicateIds, id) + t.Errorf("长时间测试发现重复ID: %d", id) + } + seen[id] = true + } + + log.Printf("长时间测试结果: 总数=%d, 唯一=%d, 重复=%d, 平均速率=%.2f ID/秒\n", + total, len(seen), duplicates, float64(total)/actualDuration.Seconds()) + + if len(duplicateIds) > 0 { + log.Printf("重复的ID列表: %v\n", duplicateIds[:min(len(duplicateIds), 10)]) + } + + if duplicates > 0 { + t.Fatalf("长时间测试发现 %d 个重复ID!", duplicates) + } +} + +// 单秒内超过10万次调用的极限测试 +func TestExceedSingleSecondLimit(t *testing.T) { + log.Println("开始单秒内超过10万次调用的极限测试...") + + // 目标:在1秒内生成超过10万个ID + const targetIds = 150000 + const maxGoroutines = 50000 + const idsPerGoroutine = targetIds / maxGoroutines + + log.Printf("目标生成 %d 个ID,使用 %d 个goroutine,每个生成 %d 个\n", + targetIds, maxGoroutines, idsPerGoroutine) + + results := make(chan int64, targetIds) + var wg sync.WaitGroup + var startSignal sync.WaitGroup + startSignal.Add(1) + + start := time.Now() + + // 启动大量goroutine + for i := 0; i < maxGoroutines; i++ { + wg.Add(1) + go func() { + defer wg.Done() + startSignal.Wait() + for j := 0; j < idsPerGoroutine; j++ { + results <- GenId() + } + }() + } + + // 同时释放所有goroutine + startSignal.Done() + wg.Wait() + close(results) + + duration := time.Since(start) + log.Printf("极限测试完成,耗时: %v\n", duration) + + // 检查重复 + seen := make(map[int64]bool) + duplicates := 0 + total := 0 + duplicateIds := make([]int64, 0) + + for id := range results { + total++ + if seen[id] { + duplicates++ + duplicateIds = append(duplicateIds, id) + t.Errorf("单秒极限测试发现重复ID: %d", id) + } + seen[id] = true + } + + log.Printf("单秒极限测试结果: 总数=%d, 唯一=%d, 重复=%d, 速率=%.2f ID/秒\n", + total, len(seen), duplicates, float64(total)/duration.Seconds()) + + if len(duplicateIds) > 0 { + log.Printf("重复的ID列表 (前10个): %v\n", duplicateIds[:min(len(duplicateIds), 10)]) + // 分析重复ID的模式 + log.Printf("分析重复ID模式...\n") + for i, dupId := range duplicateIds[:min(len(duplicateIds), 5)] { + idStr := cast.ToString(dupId) + log.Printf("重复ID %d: %s (长度: %d)\n", i+1, idStr, len(idStr)) + } + } + + if duplicates > 0 { + t.Fatalf("单秒极限测试发现 %d 个重复ID!这证明了在超高并发下存在唯一性问题", duplicates) + } else { + log.Printf("✅ 即使在 %.2f ID/秒 的极高速率下,仍然保持了唯一性\n", float64(total)/duration.Seconds()) + } +} + +// 模拟真实业务场景的混合压力测试 +func TestRealWorldMixedStress(t *testing.T) { + log.Println("开始模拟真实业务场景的混合压力测试...") + + const duration = 5 * time.Second + const normalGoroutines = 100 // 正常业务goroutine + const burstGoroutines = 2000 // 突发流量goroutine + const burstInterval = 1 * time.Second // 突发间隔 + + results := make(chan int64, 500000) + var wg sync.WaitGroup + stop := make(chan struct{}) + + start := time.Now() + + // 启动正常业务流量 + for i := 0; i < normalGoroutines; i++ { + wg.Add(1) + go func(id int) { + defer wg.Done() + for { + select { + case <-stop: + return + default: + results <- GenId() + time.Sleep(time.Millisecond * time.Duration(10+id%20)) // 模拟不同的业务处理时间 + } + } + }(i) + } + + // 定期产生突发流量 + go func() { + ticker := time.NewTicker(burstInterval) + defer ticker.Stop() + + for { + select { + case <-stop: + return + case <-ticker.C: + log.Printf("触发突发流量: %d 个并发请求\n", burstGoroutines) + // 突发大量并发请求 + var burstWg sync.WaitGroup + for i := 0; i < burstGoroutines; i++ { + burstWg.Add(1) + go func() { + defer burstWg.Done() + results <- GenId() + }() + } + burstWg.Wait() + } + } + }() + + // 运行指定时间 + time.Sleep(duration) + close(stop) + wg.Wait() + close(results) + + actualDuration := time.Since(start) + log.Printf("混合压力测试完成,实际耗时: %v\n", actualDuration) + + // 检查重复 + seen := make(map[int64]bool) + duplicates := 0 + total := 0 + duplicateIds := make([]int64, 0) + + for id := range results { + total++ + if seen[id] { + duplicates++ + duplicateIds = append(duplicateIds, id) + t.Errorf("混合压力测试发现重复ID: %d", id) + } + seen[id] = true + } + + log.Printf("混合压力测试结果: 总数=%d, 唯一=%d, 重复=%d, 平均速率=%.2f ID/秒\n", + total, len(seen), duplicates, float64(total)/actualDuration.Seconds()) + + if len(duplicateIds) > 0 { + log.Printf("重复的ID列表: %v\n", duplicateIds[:min(len(duplicateIds), 10)]) + } + + if duplicates > 0 { + t.Fatalf("混合压力测试发现 %d 个重复ID!", duplicates) + } else { + log.Printf("✅ 在真实业务场景模拟下保持了唯一性\n") + } +} + +// 最极端的多核心并发测试 +func TestExtremeMultiCoreStress(t *testing.T) { + log.Println("开始最极端的多核心并发测试...") + + // 获取CPU核心数 + numCPU := runtime.NumCPU() + runtime.GOMAXPROCS(numCPU) + log.Printf("使用 %d 个CPU核心\n", numCPU) + + // 每个核心启动合理数量的goroutine + const goroutinesPerCore = 1000 + const idsPerGoroutine = 100 + totalGoroutines := numCPU * goroutinesPerCore + totalIds := totalGoroutines * idsPerGoroutine + + log.Printf("启动 %d 个goroutine (每核心%d个),总共生成 %d 个ID\n", + totalGoroutines, goroutinesPerCore, totalIds) + + results := make(chan int64, totalIds) + var wg sync.WaitGroup + var startSignal sync.WaitGroup + startSignal.Add(1) + + start := time.Now() + + // 为每个CPU核心启动goroutine + for core := 0; core < numCPU; core++ { + for i := 0; i < goroutinesPerCore; i++ { + wg.Add(1) + go func(coreId, goroutineId int) { + defer wg.Done() + // 绑定到特定CPU核心(尽力而为) + runtime.LockOSThread() + defer runtime.UnlockOSThread() + + startSignal.Wait() + for j := 0; j < idsPerGoroutine; j++ { + results <- GenId() + // 故意不加任何延迟,最大化并发冲突 + } + }(core, i) + } + } + + // 同时释放所有goroutine + startSignal.Done() + wg.Wait() + close(results) + + duration := time.Since(start) + log.Printf("多核心极限测试完成,耗时: %v\n", duration) + + // 检查重复 + seen := make(map[int64]bool) + duplicates := 0 + total := 0 + duplicateIds := make([]int64, 0) + + for id := range results { + total++ + if seen[id] { + duplicates++ + duplicateIds = append(duplicateIds, id) + t.Errorf("多核心极限测试发现重复ID: %d", id) + } + seen[id] = true + } + + log.Printf("多核心极限测试结果: 总数=%d, 唯一=%d, 重复=%d, 速率=%.2f ID/秒\n", + total, len(seen), duplicates, float64(total)/duration.Seconds()) + + if len(duplicateIds) > 0 { + log.Printf("重复的ID列表 (前10个): %v\n", duplicateIds[:min(len(duplicateIds), 10)]) + } + + if duplicates > 0 { + t.Fatalf("多核心极限测试发现 %d 个重复ID!", duplicates) + } else { + log.Printf("✅ 在 %d 核心、%.2f ID/秒 的极限条件下仍然保持唯一性\n", + numCPU, float64(total)/duration.Seconds()) + } +} + +// 故意制造时间冲突的恶意测试 +func TestMaliciousTimeConflict(t *testing.T) { + log.Println("开始故意制造时间冲突的恶意测试...") + + // 这个测试试图在完全相同的时间点生成ID + const rounds = 100 + const goroutinesPerRound = 1000 + + allResults := make([]int64, 0, rounds*goroutinesPerRound) + var globalMutex sync.Mutex + + for round := 0; round < rounds; round++ { + log.Printf("第 %d 轮时间冲突测试\n", round+1) + + results := make(chan int64, goroutinesPerRound) + var wg sync.WaitGroup + var startSignal sync.WaitGroup + startSignal.Add(1) + + // 启动goroutine但不让它们开始 + for i := 0; i < goroutinesPerRound; i++ { + wg.Add(1) + go func() { + defer wg.Done() + startSignal.Wait() + // 在完全相同的时刻调用GenId + results <- GenId() + }() + } + + // 等待一个随机的短时间,然后同时释放所有goroutine + time.Sleep(time.Microsecond * time.Duration(rand.Intn(1000))) + startSignal.Done() + wg.Wait() + close(results) + + // 收集这一轮的结果 + roundResults := make([]int64, 0, goroutinesPerRound) + for id := range results { + roundResults = append(roundResults, id) + } + + globalMutex.Lock() + allResults = append(allResults, roundResults...) + globalMutex.Unlock() + + // 检查这一轮内部是否有重复 + roundSeen := make(map[int64]bool) + roundDuplicates := 0 + for _, id := range roundResults { + if roundSeen[id] { + roundDuplicates++ + t.Errorf("第%d轮发现重复ID: %d", round+1, id) + } + roundSeen[id] = true + } + + if roundDuplicates > 0 { + log.Printf("⚠️ 第%d轮发现 %d 个重复ID\n", round+1, roundDuplicates) + } + } + + // 检查全局重复 + log.Println("检查全局重复...") + globalSeen := make(map[int64]bool) + globalDuplicates := 0 + duplicateIds := make([]int64, 0) + + for _, id := range allResults { + if globalSeen[id] { + globalDuplicates++ + duplicateIds = append(duplicateIds, id) + t.Errorf("恶意时间冲突测试发现重复ID: %d", id) + } + globalSeen[id] = true + } + + log.Printf("恶意时间冲突测试结果: 总数=%d, 唯一=%d, 重复=%d\n", + len(allResults), len(globalSeen), globalDuplicates) + + if len(duplicateIds) > 0 { + log.Printf("重复的ID列表: %v\n", duplicateIds[:min(len(duplicateIds), 20)]) + } + + if globalDuplicates > 0 { + t.Fatalf("恶意时间冲突测试发现 %d 个重复ID!这证明了在极端时间冲突下存在问题", globalDuplicates) + } else { + log.Printf("✅ 即使在故意制造的时间冲突下仍然保持唯一性\n") + } +} + +// 性能对比测试:int64 vs string 版本 +func TestPerformanceComparison(t *testing.T) { + log.Println("开始性能对比测试: GenId (int64) vs GenSid (string)") + + const iterations = 1000000 + const goroutines = 1000 + const idsPerGoroutine = iterations / goroutines + + // 测试 GenId (int64版本) + log.Printf("测试 GenId (int64版本): %d 个goroutine,每个生成 %d 个ID\n", goroutines, idsPerGoroutine) + start1 := time.Now() + + var wg1 sync.WaitGroup + for i := 0; i < goroutines; i++ { + wg1.Add(1) + go func() { + defer wg1.Done() + for j := 0; j < idsPerGoroutine; j++ { + _ = GenId() + } + }() + } + wg1.Wait() + + duration1 := time.Since(start1) + rate1 := float64(iterations) / duration1.Seconds() + log.Printf("GenId (int64) 结果: 耗时=%v, 速率=%.2f ID/秒\n", duration1, rate1) + + // 测试 GenSid (string版本) + log.Printf("测试 GenSid (string版本): %d 个goroutine,每个生成 %d 个ID\n", goroutines, idsPerGoroutine) + start2 := time.Now() + + var wg2 sync.WaitGroup + for i := 0; i < goroutines; i++ { + wg2.Add(1) + go func() { + defer wg2.Done() + for j := 0; j < idsPerGoroutine; j++ { + _ = GenSid() + } + }() + } + wg2.Wait() + + duration2 := time.Since(start2) + rate2 := float64(iterations) / duration2.Seconds() + log.Printf("GenSid (string) 结果: 耗时=%v, 速率=%.2f ID/秒\n", duration2, rate2) + + // 性能对比分析 + speedupPercent := ((rate2 - rate1) / rate1) * 100 + log.Printf("\n📊 性能对比分析:\n") + log.Printf("GenId (int64): %.2f ID/秒\n", rate1) + log.Printf("GenSid (str): %.2f ID/秒\n", rate2) + + if speedupPercent > 0 { + log.Printf("✅ GenSid 比 GenId 快 %.2f%%\n", speedupPercent) + } else { + log.Printf("⚠️ GenSid 比 GenId 慢 %.2f%%\n", -speedupPercent) + } + + // 验证两个版本生成的ID格式一致性 + log.Println("\n🔍 验证ID格式一致性:") + for i := 0; i < 5; i++ { + intId := GenId() + strId := GenSid() + log.Printf("GenId: %d (长度: %d), GenSid: %s (长度: %d)\n", + intId, len(cast.ToString(intId)), strId, len(strId)) + } +} + +// Benchmark测试 +func BenchmarkGenId(b *testing.B) { + b.ResetTimer() + b.RunParallel(func(pb *testing.PB) { + for pb.Next() { + _ = GenId() + } + }) +} + +func BenchmarkGenSid(b *testing.B) { + b.ResetTimer() + b.RunParallel(func(pb *testing.PB) { + for pb.Next() { + _ = GenSid() + } + }) +} + +// 长时间性能对比测试 - 延长测试时间获得更准确的性能数据 +func TestExtendedPerformanceComparison(t *testing.T) { + log.Println("开始长时间性能对比测试: GenId (int64) vs GenSid (string)") + + const duration = 10 * time.Second // 延长到10秒 + const goroutines = 500 + + // 测试GenId (int64版本) + log.Printf("测试 GenId (int64版本): %d 个goroutine,持续 %v", goroutines, duration) + start1 := time.Now() + + results1 := make(chan int64, 100000) + var wg1 sync.WaitGroup + stop1 := make(chan struct{}) + + for i := 0; i < goroutines; i++ { + wg1.Add(1) + go func() { + defer wg1.Done() + for { + select { + case <-stop1: + return + case results1 <- GenId(): + // 无延迟,最大化性能测试 + } + } + }() + } + + time.Sleep(duration) + close(stop1) + wg1.Wait() + close(results1) + + duration1 := time.Since(start1) + count1 := len(results1) + rate1 := float64(count1) / duration1.Seconds() + + log.Printf("GenId (int64) 结果: 耗时=%v, 总数=%d, 速率=%.2f ID/秒", duration1, count1, rate1) + + // 测试GenSid (string版本) + log.Printf("测试 GenSid (string版本): %d 个goroutine,持续 %v", goroutines, duration) + start2 := time.Now() + + results2 := make(chan string, 100000) + var wg2 sync.WaitGroup + stop2 := make(chan struct{}) + + for i := 0; i < goroutines; i++ { + wg2.Add(1) + go func() { + defer wg2.Done() + for { + select { + case <-stop2: + return + case results2 <- GenSid(): + // 无延迟,最大化性能测试 + } + } + }() + } + + time.Sleep(duration) + close(stop2) + wg2.Wait() + close(results2) + + duration2 := time.Since(start2) + count2 := len(results2) + rate2 := float64(count2) / duration2.Seconds() + + log.Printf("GenSid (string) 结果: 耗时=%v, 总数=%d, 速率=%.2f ID/秒", duration2, count2, rate2) + + // 性能对比分析 + log.Println("\n📊 长时间性能对比分析:") + log.Printf("GenId (int64): %.2f ID/秒", rate1) + log.Printf("GenSid (str): %.2f ID/秒", rate2) + + if rate2 > rate1 { + percentage := ((rate2 - rate1) / rate1) * 100 + log.Printf("✅ GenSid 比 GenId 快 %.2f%%", percentage) + } else { + percentage := ((rate1 - rate2) / rate2) * 100 + log.Printf("⚠️ GenId 比 GenSid 快 %.2f%%", percentage) + } + + // 验证ID格式一致性 + log.Println("\n🔍 验证ID格式一致性:") + for i := 0; i < 5; i++ { + id1 := GenId() + id2 := GenSid() + log.Printf("GenId: %d (长度: %d), GenSid: %s (长度: %d)", + id1, len(cast.ToString(id1)), id2, len(id2)) + } +} + +// 辅助函数 +func min(a, b int) int { + if a < b { + return a + } + return b +}