Golang 按行解析日誌測試 ldetool

比較早的時候寫過一篇 Python Golang 解析web日誌正則一例 當時發現 Golang的正則模塊性能不是很好。最近在逛 reddit的時候發現了這樣一篇文章 Fast log parsing with Go ,文中提到了一個基於行做半結構化解析的庫ldetool, 於是又做了一些嘗試和學習。

ldetool 這個工具更像一個DSL,通過一種語法來寫解析的語法,然後通過 ldetool generate 命令來生成 golang 代碼,這個代碼就是針對某中格式單行的解析方法,詳細的教程大家可以參考 https://github.com/sirkon/ldetool/blob/master/README.md ,下面是一個簡單的測試過程的記錄。

測試的環境 Mac Pro 8G4Core,粗略的看下性能,並不嚴謹

ldetool

安裝

通過 go get就可以安裝, 安裝之後就是個命令

▶ go version
go version go1.11 darwin/amd64

go get -u github.com/sirkon/ldetool

▶ ldetool -v
ldetool version 0.0.0

場景

測試的樣本是類似nginx的access log文件,格式如下

27.154.70.117 - - [20/Nov/2018:20:23:56 +0800] 2 "GET http://7img1.tianlaikge.com/tv/homeimage/201709/shengridangao.zip HTTP/1.1" 200 842186 841382 "-" "-" "Dalvik/2.1.0 (Linux; U; Android 7.1.2; vivo Y79A Build/N2G47H)" "-" 219082621 "HIT" 27.159.73.35

測試需求,解析30M左右的日誌文件,大概12w行,計算總流量(流量字段爲 842186)

分析

這種日誌文件有幾個特點

  • 每個記錄就是一行文件
  • 雖然是文本,但是不是完全的無結構,算半結構化
  • 上下行基本無關,可以並行處理

通常的解析方案

  • 使用正則表達式(後面有個python版本的使用正則來分析)
  • 使用split方法,根據特徵分隔符來分割,例如空格,雙引號
  • 使用DSL,本質還是類似split,不過是通過代碼生成器自動生成解析代碼(上面提到的 ldetool 命令啦)

測試

源代碼在 https://github.com/orangle/snippets/tree/master/golang/log_parse ,主要是對比split方式和ldetool生成的代碼的性能(因爲之前測試regex效果並不好,這裏沒有加入測試)

直接執行函數,使用 time 來測量的結果(多次測試下來,下面兩個算是平均值)

# split
▶ time go run main.go nginx_lde.go
total:  96130191409
go run main.go nginx_lde.go  1.80s user 0.25s system 106% cpu 1.914 total

# ldetool
▶ time go run main.go nginx_lde.go
total:  96130191409
go run main.go nginx_lde.go  1.36s user 0.23s system 108% cpu 1.464 total

使用 golang test benckmark 測量的結果

▶ go test -bench=. -benchmem
total:  96130191409
goos: darwin
goarch: amd64
pkg: log_parse
BenchmarkSplit-4     	       1	1549334472 ns/op	512189744 B/op	 1629989 allocs/op
total:  96130191409
BenchmarkLdetool-4   	       1	1052007947 ns/op	 2996064 B/op	   24805 allocs/op
PASS
ok  	log_parse	2.608s

總的來看,ldetool還是能快40~50%的,內存使用和內存分配更是少了很多。

Python

之後我還做了個同樣樣本的Python測試,主要是正則表達式和split方式的對比,也可以參照golang的結果對比。

代碼在 https://github.com/orangle/snippets/tree/master/python/regex_vs_split

python re, re沒有 compile

▶ python regex_vs_split.py
total bytes: 96130099518 cost: 5.805 qps: 92174.132

python re, re compile之後

▶ python regex_vs_split.py
total bytes: 96130099518 cost: 5.324 qps: 100500.519

python split 之後分析

▶ python regex_vs_split.py
total bytes: 96130191409 cost: 3.957 qps: 135215.152

這樣看起來 split要比 regex 快一些,但是比golang又慢蠻多的。

End

下次在遇到這種需求,可以嘗試下 ldetool

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章