2 回答
TA贡献2012条经验 获得超12个赞
我试图将您的问题提炼成一个非常简单的例子。
由于可能有“数十万个正则表达式匹配”,我为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 main
import (
"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
}
}
}
- 2 回答
- 0 关注
- 248 浏览
添加回答
举报