zap日誌框架 效能篇 3

2021-10-06 08:02:42 字數 3847 閱讀 6901

zap日誌框架分了三篇來講解:使用篇 ,原始碼篇,效能篇。

我們在github上可以看到如下測試結果:

msg+10個fields的情況

package

time

time % to zap

objects allocated

⚡ zap

862 ns/op

+0%5 allocs/op

⚡ zap (sugared)

1250 ns/op

+45%

11 allocs/op

zerolog

4021 ns/op

+366%

76 allocs/op

go-kit

4542 ns/op

+427%

105 allocs/op

apex/log

26785 ns/op

+3007%

115 allocs/op

logrus

29501 ns/op

+3322%

125 allocs/op

log15

29906 ns/op

+3369%

122 allocs/op

可以看到,在此基準測試下,zap是遠遠領先於其他的日誌框架。那是什麼原因讓zap有如此優異的效能呢,我相信很多讀者和我一樣,按捺不住的想一**竟。

pool能有效的減少objects allocated,減少gc。

checkedentry

checkedentry含有entry,core屬性,每次列印日誌都需要呼叫checkedentry的write方法,因此使用的頻率非常高

//獲取並組裝checkedentry 物件

func

(ce *checkedentry)

addcore

(ent entry, core core)

*checkedentry

ce.cores =

(ce.cores, core)

return ce

}//對pool中獲取checkedentry物件

func

getcheckedentry()

*checkedentry

以下物件池的定義,需要注意的是:zap預分配了4個長度的core空間,面對core數量的不確定的性,可以有效的防止slice的記憶體複製

var

( _cepool = sync.pool}}

)

buffer

buffer是乙個byte slice封裝。還自帶乙個pool,用於free(內部也是呼叫的物件池的put**操作)。

type buffer struct

type pool struct

// newpool constructs a new pool.

func

newpool

() pool },

}}}

buffer在zap中有兩處用到:

乙個是entrycaller,用於輸出呼叫者的path資訊;

乙個是jsonencoder,用於日誌編碼,輸出json或者console個數的日誌

上面的兩個pool都和輸出日誌有關,所以說zap在輸出日誌的時候,做到了儘量減少物件分配,這一點非常值得我們借鑑,我們是否也可以在高使用頻率的物件上使用pool來提高效率,減少gc,進而儘量減少stw的頻率和時間

如果要講物件編碼成json格式,最容易想到的就是:json.marshal(v inte***ce{}),這是go庫自帶的,使用起來非常簡單,但通過原始碼發現,json的編碼都是通過反射來實現的,如下:

func

(e *encodestate)

marshal

(v inte***ce

, opts encopts)

(err error

)else}}

()e.reflectvalue

(reflect.

valueof

(v), opts)

return

nil}

反射雖然好用,但是對效率不太友好,這就是zap為什麼要自建encoder原因,那我們來看下encoder的**片段,看看encoder是怎麼實現json的拼裝的

//根據field的型別,做對應的add操作,這裡並不是通過反射來實現的

func

(f field)

addto

(enc objectencoder)

func

(enc *jsonencoder)

addbinary

(key string

, val [

]byte

)func

(enc *jsonencoder)

addstring

(key, val string

)//拼接json的key

func

(enc *jsonencoder)

addkey

(key string)}

//拼接json的value

func

(enc *jsonencoder)

(val string

)

寫時複製,簡單的理解就是:在讀的時候,多個物件共享乙個記憶體區,只有在寫的時候,才會新開闢乙個記憶體空間,賦予要寫的物件,這樣就不會與原來的物件發生衝突

如果不採用寫時複製,就需要加鎖,加鎖相對於重新分配記憶體,更加損耗效能。我們看看zap有哪些地方做了寫時複製:統一用的clone方法

加入option屬性,複製log物件

func (log *logger) withoptions(opts ...option) *logger 

return c

}

加入field物件,複製log物件

func

(log *logger)

with

(fields ...field)

*logger

l := log.

clone()

l.core = l.core.

with

(fields)

return l

}

加入field物件,複製core物件

func

(c *iocore)

with

(fields [

]field) core

複製encoder物件

func

(c *iocore)

clone()

*iocore

}

就不一一枚舉了,我們可以自行進行全域性搜尋clone()方法,找到結果

zap 在效能上做了非常精細的考量,有如下方面

zap日誌框架-使用篇(1)

zap日誌框架-原始碼篇(2)

scrapy框架的日誌及提高效能

目錄實戰 使用scrapy crawl spiderfilename執行程式時,在終端裡列印輸出的就是scrapy的日誌資訊。日誌資訊的種類 error 一般錯誤 warning 警告 info 一般的資訊 debug 除錯資訊設定日誌資訊指定輸出 在settings.py配置檔案中,加入 log ...

效能測試(3)JMETER操作篇

gui模式 gui模式為圖形介面格式,友善度較高。可以直觀編寫或錄製指令碼。但實際測試過程中,資源損耗較高,jmeter官方並不建議效能測試場景中使用,僅作為指令碼錄製和除錯。若為分布式壓力,控制機可以選擇用gui模式,但由於控制機需要和所有的壓力機互動測試結果,可能造成結果缺失。盡量也不使用。若需...

SAP R 3 效能調優 記憶體篇

sap r 3 效能調優 記憶體篇 一.記憶體概覽 說明 系統能夠使用的記憶體大小 即虛擬記憶體 一定小於或等於物理記憶體與swap容量的總和 64位unix要求至少20 gb的swap file 當同一伺服器包含oracle資料庫和sap例項的系統 即central system 時,使用的記憶體...