繁花如伊
我试图将您的问题提炼成一个非常简单的例子。由于可能有“数十万个正则表达式匹配”,我为matches切片容量做了大量的初始分配 1 M (1024 * 1024) 个条目。切片是一种引用类型。在 64 位操作系统上,切片标头“结构”具有长度、容量和总共 24 (3 * 8) 个字节的指针。因此,对 1 M 个条目的切片的初始分配仅为 24 (24 * 1) MB。如果条目超过 1 M,则将分配容量为 1.25 (1 + 1 / 4) M 个条目的新切片,并将现有的 1 M 切片标头条目 (24 MB) 复制到其中。总之,您可以append通过最初过度分配切片容量来避免 many s 的大部分开销。更大的内存问题是为每个匹配保存和引用的所有数据。更大的 CPU 时间问题是执行regexp.FindAll's所花费的时间。package mainimport ( "bufio" "fmt" "os" "regexp")var searches = []*regexp.Regexp{ regexp.MustCompile("configure"), regexp.MustCompile("unknown"), regexp.MustCompile("PATH"),}var matches = make([][]byte, 0, 1024*1024)func main() { logName := "config.log" log, err := os.Open(logName) if err != nil { fmt.Fprintln(os.Stderr, err) os.Exit(1) } defer log.Close() scanner := bufio.NewScanner(log) for scanner.Scan() { line := scanner.Bytes() for _, s := range searches { for _, m := range s.FindAll(line, -1) { matches = append(matches, append([]byte(nil), m...)) } } } if err := scanner.Err(); err != nil { fmt.Fprintln(os.Stderr, err) } // Output matches fmt.Println(len(matches)) for i, m := range matches { fmt.Println(string(m)) if i >= 16 { break } }}