
Go语言文本去重性能优化
本文分析并优化一段Go语言代码,该代码用于处理75万行文本的去重任务,原始耗时17秒。优化目标是提升文本去重效率。
原始代码分析及问题:
原始代码使用map[string]bool存储去重结果,并通过字符串拼接累积结果字符串。这存在两个主要性能瓶颈:
立即学习“go语言免费学习笔记(深入)”;
-
字符串拼接效率低:
result += fmt.Sprintf(...)这种方式会不断创建新的字符串,导致频繁的内存分配和复制,效率低下。 -
map动态扩容:
make(map[string]bool, 0)未预分配map容量,随着数据增加,map会频繁扩容,造成性能损耗。
优化策略:
针对上述问题,我们采用以下优化策略:
-
使用
strings.Builder: 将字符串拼接替换为strings.Builder,它提供更高效的字符串构建方式,避免了频繁的内存分配和复制。 -
预分配
map容量: 初始化map时预分配一定容量,例如make(map[string]struct{}, 1000000),减少扩容次数。使用struct{}作为map值,可以节省内存,因为它不占用任何空间。
优化后的代码:
package distinct
import (
"bufio"
"fmt"
"io"
"os"
"strings"
)
//distinctfile 为指定文件去重
func distinctfile(file string, output string) {
f, err := os.Open(file)
if err != nil {
fmt.Println(err)
return
}
defer f.Close()
reader := bufio.NewReader(f)
set := make(map[string]struct{}, 1000000) // 预分配map容量
builder := strings.Builder{} // 使用strings.Builder
for {
line, isPrefix, err := reader.ReadLine()
if err == io.EOF {
break
}
if err != nil {
fmt.Println(err)
return
}
if !isPrefix {
lineStr := string(line)
if _, ok := set[lineStr]; !ok {
builder.WriteString(lineStr)
builder.WriteString("\n")
set[lineStr] = struct{}{}
}
}
}
nf, err := os.Create(output)
if err != nil {
fmt.Println(err)
return
}
defer nf.Close()
_, err = io.Copy(nf, strings.NewReader(builder.String()))
if err != nil {
fmt.Println(err)
}
}
测试代码 (保持不变):
package distinct
import "testing"
func TestDistinctFile(t *testing.T) {
distinctfile("result.txt", "out.txt")
}
通过以上优化,预计可以显著减少文本去重的时间消耗。 预分配的map大小可以根据实际文本行数进行调整,以达到最佳性能。 此外,考虑使用并发处理进一步提升效率也是一个可行的方向,但需要更复杂的代码设计。










