插件窝 干货文章 Go语言文本去重耗时17秒,如何优化才能提升性能?

Go语言文本去重耗时17秒,如何优化才能提升性能?

uniqueTexts string texts text 451    来源:    2025-03-15

在Go语言中进行文本去重时,如果耗时较长,可以通过以下几种方式进行优化:

1. 使用更高效的数据结构

Go语言中的map数据结构在查找和插入操作上具有O(1)的时间复杂度,因此使用map来存储已经出现的文本可以显著提高去重效率。

func Deduplicate(texts []string) []string {
    seen := make(map[string]struct{})
    uniqueTexts := make([]string, 0, len(texts))

    for _, text := range texts {
        if _, exists := seen[text]; !exists {
            seen[text] = struct{}{}
            uniqueTexts = append(uniqueTexts, text)
        }
    }

    return uniqueTexts
}

2. 并行处理

如果文本数据量非常大,可以考虑将数据分块并行处理。Go语言的goroutinechannel可以很好地支持并发处理。

func DeduplicateParallel(texts []string) []string {
    numWorkers := 4
    chunkSize := (len(texts) + numWorkers - 1) / numWorkers

    var wg sync.WaitGroup
    wg.Add(numWorkers)

    uniqueTexts := make(chan string, len(texts))

    for i := 0; i < numWorkers; i++ {
        go func(i int) {
            defer wg.Done()
            start := i * chunkSize
            end := start + chunkSize
            if end > len(texts) {
                end = len(texts)
            }

            seen := make(map[string]struct{})
            for _, text := range texts[start:end] {
                if _, exists := seen[text]; !exists {
                    seen[text] = struct{}{}
                    uniqueTexts <- text
                }
            }
        }(i)
    }

    go func() {
        wg.Wait()
        close(uniqueTexts)
    }()

    result := make([]string, 0, len(texts))
    for text := range uniqueTexts {
        result = append(result, text)
    }

    return result
}

3. 减少内存分配

频繁的内存分配和垃圾回收会影响性能。可以通过预分配内存来减少内存分配次数。

func DeduplicatePrealloc(texts []string) []string {
    seen := make(map[string]struct{}, len(texts))
    uniqueTexts := make([]string, 0, len(texts))

    for _, text := range texts {
        if _, exists := seen[text]; !exists {
            seen[text] = struct{}{}
            uniqueTexts = append(uniqueTexts, text)
        }
    }

    return uniqueTexts
}

4. 使用更高效的字符串比较

如果文本数据中有大量重复的字符串,可以考虑使用strings.Builderbytes.Buffer来减少字符串比较的开销。

func DeduplicateEfficient(texts []string) []string {
    seen := make(map[string]struct{}, len(texts))
    uniqueTexts := make([]string, 0, len(texts))

    var sb strings.Builder
    for _, text := range texts {
        sb.Reset()
        sb.WriteString(text)
        key := sb.String()

        if _, exists := seen[key]; !exists {
            seen[key] = struct{}{}
            uniqueTexts = append(uniqueTexts, text)
        }
    }

    return uniqueTexts
}

5. 使用外部库

如果以上方法仍然不能满足性能需求,可以考虑使用一些高性能的外部库,如github.com/cespare/xxhash等,来进行更高效的哈希计算。

import (
    "github.com/cespare/xxhash"
    "sync"
)

func DeduplicateWithHash(texts []string) []string {
    seen := make(map[uint64]struct{}, len(texts))
    uniqueTexts := make([]string, 0, len(texts))
    var mu sync.Mutex

    var wg sync.WaitGroup
    wg.Add(len(texts))

    for _, text := range texts {
        go func(text string) {
            defer wg.Done()
            hash := xxhash.Sum64String(text)

            mu.Lock()
            if _, exists := seen[hash]; !exists {
                seen[hash] = struct{}{}
                uniqueTexts = append(uniqueTexts, text)
            }
            mu.Unlock()
        }(text)
    }

    wg.Wait()
    return uniqueTexts
}

6. 使用更高效的算法

如果文本数据量非常大,可以考虑使用布隆过滤器(Bloom Filter)等概率数据结构来减少内存使用和提高去重效率。

import (
    "github.com/willf/bloom"
)

func DeduplicateWithBloomFilter(texts []string) []string {
    filter := bloom.New(1000000, 5) // 根据需要调整参数
    uniqueTexts := make([]string, 0, len(texts))

    for _, text := range texts {
        if !filter.TestString(text) {
            filter.AddString(text)
            uniqueTexts = append(uniqueTexts, text)
        }
    }

    return uniqueTexts
}

总结

通过使用更高效的数据结构、并行处理、减少内存分配、使用外部库或更高效的算法,可以显著提升Go语言中文本去重的性能。具体选择哪种优化方式,需要根据实际的数据规模和性能需求来决定。