fscan/Common/utils/benchmark_test.go
ZacharyZcR 291da0c879 refactor: 清理内存优化工具包中的死代码函数
根据静态分析结果清理未使用的函数:

删除文件:
- Common/utils/mappool.go (整个Map对象池模块未被使用)

精简文件:
- Common/utils/slicepool.go: 移除未使用的池管理函数,保留核心去重功能
- Common/utils/stringbuilder.go: 移除未使用的格式化和统计函数
- Common/utils/benchmark_test.go: 更新测试以适应清理后的API

保留的核心功能:
✓ JoinStrings/JoinInts - 字符串连接优化 (18x性能提升)
✓ DeduplicateStrings - 字符串去重功能
✓ StringBuilderPool - 字符串构建器池化机制

清理效果:
- 减少约150行无用代码
- 简化API设计,提高可维护性
- 保持所有实际使用的优化功能完整性
- 编译测试和功能测试全部通过

经验证,核心的内存优化功能(字符串连接18x性能提升,99.8%内存减少)完全保留。
2025-08-07 01:17:46 +08:00

315 lines
7.2 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package utils
import (
"fmt"
"runtime"
"strings"
"testing"
"time"
)
// BenchmarkStringJoinOriginal 原始字符串连接方法
func BenchmarkStringJoinOriginal(b *testing.B) {
slice := make([]string, 100)
for i := range slice {
slice[i] = fmt.Sprintf("item-%d", i)
}
b.ResetTimer()
for i := 0; i < b.N; i++ {
var result string
if len(slice) > 0 {
result = slice[0]
for j := 1; j < len(slice); j++ {
result += "," + slice[j]
}
}
_ = result
}
}
// BenchmarkStringJoinOptimized 优化后的字符串连接方法
func BenchmarkStringJoinOptimized(b *testing.B) {
slice := make([]string, 100)
for i := range slice {
slice[i] = fmt.Sprintf("item-%d", i)
}
b.ResetTimer()
for i := 0; i < b.N; i++ {
result := JoinStrings(slice, ",")
_ = result
}
}
// BenchmarkIntJoinOriginal 原始整数连接方法
func BenchmarkIntJoinOriginal(b *testing.B) {
slice := make([]int, 100)
for i := range slice {
slice[i] = i * 10
}
b.ResetTimer()
for i := 0; i < b.N; i++ {
var result string
if len(slice) > 0 {
result = fmt.Sprintf("%d", slice[0])
for j := 1; j < len(slice); j++ {
result += "," + fmt.Sprintf("%d", slice[j])
}
}
_ = result
}
}
// BenchmarkIntJoinOptimized 优化后的整数连接方法
func BenchmarkIntJoinOptimized(b *testing.B) {
slice := make([]int, 100)
for i := range slice {
slice[i] = i * 10
}
b.ResetTimer()
for i := 0; i < b.N; i++ {
result := JoinInts(slice, ",")
_ = result
}
}
// BenchmarkDeduplicateOriginal 原始去重方法
func BenchmarkDeduplicateOriginal(b *testing.B) {
slice := make([]string, 1000)
for i := range slice {
slice[i] = fmt.Sprintf("item-%d", i%100) // 10倍重复
}
b.ResetTimer()
for i := 0; i < b.N; i++ {
temp := make(map[string]struct{})
var result []string
for _, item := range slice {
if _, exists := temp[item]; !exists {
temp[item] = struct{}{}
result = append(result, item)
}
}
_ = result
}
}
// BenchmarkDeduplicateOptimized 优化后的去重方法
func BenchmarkDeduplicateOptimized(b *testing.B) {
slice := make([]string, 1000)
for i := range slice {
slice[i] = fmt.Sprintf("item-%d", i%100) // 10倍重复
}
b.ResetTimer()
for i := 0; i < b.N; i++ {
result := DeduplicateStrings(slice)
_ = result
}
}
// BenchmarkSliceAllocationOriginal 原始切片分配方法
func BenchmarkSliceAllocationOriginal(b *testing.B) {
b.ResetTimer()
for i := 0; i < b.N; i++ {
var result []string
for j := 0; j < 50; j++ {
result = append(result, fmt.Sprintf("item-%d", j))
}
_ = result
}
}
// BenchmarkSliceAllocationOptimized 优化后的切片分配方法
func BenchmarkSliceAllocationOptimized(b *testing.B) {
b.ResetTimer()
for i := 0; i < b.N; i++ {
result := make([]string, 0, 50)
for j := 0; j < 50; j++ {
result = append(result, fmt.Sprintf("item-%d", j))
}
_ = result
}
}
// TestMemoryUsage 内存使用情况对比测试
func TestMemoryUsage(t *testing.T) {
// 测试字符串连接的内存使用
t.Run("StringJoin", func(t *testing.T) {
slice := make([]string, 1000)
for i := range slice {
slice[i] = fmt.Sprintf("test-string-%d", i)
}
// 测试原始方法
runtime.GC()
var m1, m2 runtime.MemStats
runtime.ReadMemStats(&m1)
for i := 0; i < 1000; i++ {
var result string
if len(slice) > 0 {
result = slice[0]
for j := 1; j < len(slice); j++ {
result += "," + slice[j]
}
}
_ = result
}
runtime.GC()
runtime.ReadMemStats(&m2)
origAlloc := m2.TotalAlloc - m1.TotalAlloc
// 测试优化方法
runtime.GC()
runtime.ReadMemStats(&m1)
for i := 0; i < 1000; i++ {
result := JoinStrings(slice, ",")
_ = result
}
runtime.GC()
runtime.ReadMemStats(&m2)
optAlloc := m2.TotalAlloc - m1.TotalAlloc
t.Logf("原始方法内存分配: %d bytes", origAlloc)
t.Logf("优化方法内存分配: %d bytes", optAlloc)
t.Logf("内存减少: %.2f%%", float64(origAlloc-optAlloc)/float64(origAlloc)*100)
})
}
// TestPoolReuse 测试对象池复用效果StringBuilderPool
func TestPoolReuse(t *testing.T) {
// 重置计数器
pool := NewStringBuilderPool(1024)
// 执行多次操作
slice := []string{"a", "b", "c", "d", "e"}
for i := 0; i < 100; i++ {
result := pool.JoinStrings(slice, ",")
_ = result
}
// GetReusedCount 方法已移除,无法测试复用次数
t.Log("字符串构建器池测试完成")
// 切片池相关功能已移除,跳过该测试
t.Log("切片池功能已移除")
}
// TestStringBuilderCorrectness 测试字符串构建器正确性
func TestStringBuilderCorrectness(t *testing.T) {
testCases := []struct {
slice []string
sep string
want string
}{
{[]string{}, ",", ""},
{[]string{"a"}, ",", "a"},
{[]string{"a", "b"}, ",", "a,b"},
{[]string{"hello", "world", "test"}, " ", "hello world test"},
{[]string{"1", "2", "3", "4", "5"}, "-", "1-2-3-4-5"},
}
for _, tc := range testCases {
got := JoinStrings(tc.slice, tc.sep)
want := strings.Join(tc.slice, tc.sep)
if got != want {
t.Errorf("JoinStrings(%v, %q) = %q, want %q", tc.slice, tc.sep, got, want)
}
}
}
// TestIntJoinCorrectness 测试整数连接正确性
func TestIntJoinCorrectness(t *testing.T) {
testCases := []struct {
slice []int
sep string
want string
}{
{[]int{}, ",", ""},
{[]int{1}, ",", "1"},
{[]int{1, 2}, ",", "1,2"},
{[]int{10, 20, 30}, "-", "10-20-30"},
}
for _, tc := range testCases {
got := JoinInts(tc.slice, tc.sep)
if got != tc.want {
t.Errorf("JoinInts(%v, %q) = %q, want %q", tc.slice, tc.sep, got, tc.want)
}
}
}
// BenchmarkCredentialGeneration 模拟SSH凭证生成的性能测试
func BenchmarkCredentialGeneration(b *testing.B) {
users := []string{"admin", "root", "user", "test", "guest"}
passwords := make([]string, 20)
for i := range passwords {
passwords[i] = fmt.Sprintf("password%d", i)
}
b.ResetTimer()
for i := 0; i < b.N; i++ {
// 模拟SSH凭证生成过程
totalCreds := len(users) * len(passwords)
credentials := make([]struct{ user, pass string }, 0, totalCreds)
for _, user := range users {
for _, pass := range passwords {
credentials = append(credentials, struct{ user, pass string }{user, pass})
}
}
_ = credentials
}
}
// Example 展示如何使用优化后的工具
func ExampleJoinStrings() {
slice := []string{"apple", "banana", "cherry"}
result := JoinStrings(slice, ", ")
fmt.Println(result)
// Output: apple, banana, cherry
}
func ExampleJoinInts() {
ports := []int{80, 443, 8080, 9090}
result := JoinInts(ports, ",")
fmt.Println(result)
// Output: 80,443,8080,9090
}
// 运行时长度测试 - 验证在不同规模下的表现
func TestScalability(t *testing.T) {
sizes := []int{10, 100, 1000, 5000}
for _, size := range sizes {
t.Run(fmt.Sprintf("Size%d", size), func(t *testing.T) {
// 准备数据
slice := make([]string, size)
for i := range slice {
slice[i] = fmt.Sprintf("item-%d", i)
}
start := time.Now()
result := JoinStrings(slice, ",")
duration := time.Since(start)
t.Logf("规模 %d: 耗时 %v, 结果长度 %d", size, duration, len(result))
// 验证结果正确性(只检查开头和结尾)
expected := strings.Join(slice, ",")
if result != expected {
t.Errorf("结果不匹配")
}
})
}
}