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 時,使用的記憶體...