[導讀]當今世界的任何計算機系統,每天都會生成大量的日志或數據。隨著系統的發(fā)展,將調試數據存儲到數據庫中是不可行的,因為它們是不可變的,并且只能用于分析和解決故障。所以,大部分公司傾向于將日志存儲在文件中,而這些文件通常位于本地磁盤中。我們將使用Go語言,從一個大小為16GB的.txt或...
當今世界的任何計算機系統,每天都會生成大量的日志或數據。隨著系統的發(fā)展,將調試數據存儲到數據庫中是不可行的,因為它們是不可變的,并且只能用于分析和解決故障。所以,大部分公司傾向于將日志存儲在文件中,而這些文件通常位于本地磁盤中。我們將使用Go語言,從一個大小為16GB的.txt或.log文件中提取日志。 讓我們開始編碼…… 首先,我們打開文件。對于任何文件的IO,我們都將使用標準的Go os.File。
f,?err?:=?os.Open(fileName)
?if?err?!=?nil?{
???fmt.Println("cannot?able?to?read?the?file",?err)
???return
?}
//?UPDATE:?close?after?checking?error
defer?file.Close()??//Do?not?forget?to?close?the?file
打開文件后,我們有以下兩個選項可以選擇:逐行讀取文件,這有助于減少內存緊張,但需要更多的時間。一次將整個文件讀入內存并處理該文件,這將消耗更多內存,但會顯著減少時間。由于文件太大,即16 GB,因此無法將整個文件加載到內存中。但是第一種選擇對我們來說也是不可行的,因為我們希望在幾秒鐘內處理文件。但你猜怎么著,還有第三種選擇。瞧……相比于將整個文件加載到內存中,在Go語言中,我們還可以使用bufio.NewReader()將文件分塊加載。r?:=?bufio.NewReader(f)
for?{
buf?:=?make([]byte,4*1024)?//the?chunk?size
n,?err?:=?r.Read(buf)?//loading?chunk?into?buffer
???buf?=?buf[:n]
if?n?==?0?{
???
?????if?err?!=?nil?{
???????fmt.Println(err)
???????break
?????}
?????if?err?==?io.EOF?{
???????break
?????}
?????return?err
??}
}
一旦我們將文件分塊,我們就可以分叉一個線程,即Go routine,同時處理多個文件區(qū)塊。上述代碼將修改為://sync?pools?to?reuse?the?memory?and?decrease?the?preassure?on?Garbage?Collector
linesPool?:=?sync.Pool{New:?func()?interface{}?{
????????lines?:=?make([]byte,?500*1024)
????????return?lines
}}
stringPool?:=?sync.Pool{New:?func()?interface{}?{
??????????lines?:=?""
??????????return?lines
}}
slicePool?:=?sync.Pool{New:?func()?interface{}?{
???????????lines?:=?make([]string,?100)
???????????return?lines
}}
r?:=?bufio.NewReader(f)
var?wg?sync.WaitGroup?//wait?group?to?keep?track?off?all?threads
for?{
?????
?????buf?:=?linesPool.Get().([]byte)
?????n,?err?:=?r.Read(buf)
?????buf?=?buf[:n]
if?n?==?0?{
????????if?err?!=?nil?{
????????????fmt.Println(err)
????????????break
????????}
????????if?err?==?io.EOF?{
????????????break
????????}
????????return?err
?????}
nextUntillNewline,?err?:=?r.ReadBytes('\n')//read?entire?line
?????
?????if?err?!=?io.EOF?{
?????????buf?=?append(buf,?nextUntillNewline...)
?????}
?????
?????wg.Add(1)
?????go?func()?{?
??????
????????//process?each?chunk?concurrently
????????//start?->?log?start?time,?end?->?log?end?time
????????
????????ProcessChunk(buf,? 





