2 回答

TA貢獻2012條經(jīng)驗 獲得超12個贊
我試圖將您的問題提煉成一個非常簡單的例子。
由于可能有“數(shù)十萬個正則表達式匹配”,我為matches切片容量做了大量的初始分配 1 M (1024 * 1024) 個條目。切片是一種引用類型。在 64 位操作系統(tǒng)上,切片標頭“結構”具有長度、容量和總共 24 (3 * 8) 個字節(jié)的指針。因此,對 1 M 個條目的切片的初始分配僅為 24 (24 * 1) MB。如果條目超過 1 M,則將分配容量為 1.25 (1 + 1 / 4) M 個條目的新切片,并將現(xiàn)有的 1 M 切片標頭條目 (24 MB) 復制到其中。
總之,您可以append通過最初過度分配切片容量來避免 many s 的大部分開銷。更大的內(nèi)存問題是為每個匹配保存和引用的所有數(shù)據(jù)。更大的 CPU 時間問題是執(zhí)行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 關注
- 273 瀏覽
添加回答
舉報