第七色在线视频,2021少妇久久久久久久久久,亚洲欧洲精品成人久久av18,亚洲国产精品特色大片观看完整版,孙宇晨将参加特朗普的晚宴

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

高效附加到可變長度的字符串容器(Golang)

高效附加到可變長度的字符串容器(Golang)

Go
達令說 2021-07-09 14:01:38
問題:我需要將多個正則表達式應用于大日志文件的每一行(如幾 GB 長),收集非空匹配項并將它們?nèi)糠湃胍粋€數(shù)組中(用于序列化并通過網(wǎng)絡發(fā)送)。如果這個問題的答案成立,切片沒有多大幫助:如果切片沒有足夠的容量,則 append 將需要分配新內(nèi)存并復制舊內(nèi)存。對于 <1024 個元素的切片,它將使容量加倍,對于具有 >1024 個元素的切片,它將增加 1.25 倍。由于實際上可能有數(shù)十萬個正則表達式匹配,因此我無法真正預測切片的長度/容量。我不能讓它太大或者“以防萬一” bc 這會浪費內(nèi)存(或者會嗎?如果內(nèi)存分配器足夠聰明,不會分配太多未寫入的內(nèi)存,也許我可以使用巨大的切片容量沒有太大的傷害?)。所以我正在考慮以下替代方案:有一個雙向鏈接的匹配列表(http://golang.org/pkg/container/list/)計算它的長度(會len()起作用嗎?)預分配此容量的一部分將字符串指針復制到此切片在 Go 中是否有一種不那么費力的方法來實現(xiàn)這個目標(追加 ~ O(1) 追加復雜度)?(當然這里是 golang 新手)
查看完整描述

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

        }

    }

}


查看完整回答
反對 回復 2021-07-12
  • 2 回答
  • 0 關注
  • 273 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯(lián)系客服咨詢優(yōu)惠詳情

幫助反饋 APP下載

慕課網(wǎng)APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網(wǎng)微信公眾號