CFSDN nhấn mạnh vào việc tạo ra giá trị thông qua mã nguồn mở. Chúng tôi cam kết xây dựng một nền tảng chia sẻ tài nguyên để mọi người làm CNTT có thể tìm thấy thế giới tuyệt vời của riêng mình tại đây.
Bài đăng trên blog CFSDN này, Giải thích chi tiết về Tối ưu hóa đầu ra nhật ký của Golang log4go, được tác giả thu thập và biên soạn. Nếu bạn quan tâm đến bài viết này, vui lòng thích nó.
Lời nói đầu.
Trong ngôn ngữ Go, một mô-đun nhật ký nhất định đã được tích hợp. Các nhà phát triển có thể sử dụng gói nhật ký riêng của ngôn ngữ Go (nhập "log"). Ngoài ra còn có nhiều gói nguồn mở có nhật ký riêng. Đối với một số phát triển đơn giản, bản thân mô-đun nhật ký là đủ. Tuy nhiên, đối với một số dự án phát triển lớn và phức tạp, nhật ký cần được xuất ra theo nhiều danh mục khác nhau hoặc thông qua mạng và bản thân mô-đun nhật ký sẽ khó xử lý.
Ngoài ra còn có một số mô-đun nhật ký tương đối nặng, chẳng hạn như logrus, có thể triển khai các chức năng phức tạp hơn. Ở đây chúng tôi giới thiệu một mô-đun nhật ký nhẹ - log4go.
Gần đây, tôi đã đọc một số gói nhật ký golang và các bài viết liên quan, đồng thời đọc kỹ nhật ký và go-log do hệ thống go 1.9.2 cung cấp, điều này đã cho tôi ý tưởng tối ưu hóa đầu ra nhật ký của log4go.
Cấu trúc với multiwriter.
Nhật ký sử dụng multiwriter để hỗ trợ nhiều đầu ra nhật ký và sử dụng khóa Mutex để giải quyết xung đột trong đầu ra nhật ký đa luồng. log4go sử dụng lập trình có cấu trúc để chuyển các bản ghi nhật ký LogRecord bằng các kênh.
Ban đầu tôi nghĩ rằng kênh truyền hình sẽ hiệu quả hơn... nhưng thực ra đây là quan điểm sai lầm. Kênh là hàng đợi bị khóa toàn cục có thể được sử dụng để khóa, nhưng hiệu quả tương đối thấp. Bởi vì nó có các chức năng bổ sung như truyền dữ liệu, phối hợp xử lý tuần tự, thời gian chờ, v.v. và không chỉ đơn thuần là khóa. Nó không giống với Mutex.
log4go đưa đầu ra nhật ký màn hình termlog vào cấu trúc, điều này gây ra một vấn đề nhỏ. Khi chúng ta sử dụng log4go để gỡ lỗi applet, nó chạy quá nhanh và chương trình thoát trước khi goroutine termlog bắt đầu chạy. Kết quả là không có nhật ký nào được hiển thị trên màn hình. Vấn đề này chỉ có thể được giải quyết bằng cách thêm độ trễ vào Close() và chờ goroutine khởi động. Sau đó kiểm tra kênh...
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
hai mươi mốt
hai mươi hai
hai mươi ba
hai mươi bốn
25
|
func (f *Filter) Đóng() {
nếu như
f.đóng {
trở lại
}
vì
i := 10; i > 0; i-- {
thời gian
.Ngủ(100 *
thời gian
.Mili giây)
nếu như
len(f.rec) <= 0 {
phá vỡ
}
}
f.đóng =
ĐÚNG VẬY
hoãn f.LogWriter.Close()
đóng(f.rec)
nếu như
len(f.rec) <= 0 {
trở lại
}
vì
rec := phạm vi f.rec {
f.LogWrite(rec)
}
}
|
log trực tiếp xuất thông tin nhật ký đã định dạng ra màn hình, đơn giản hơn nhiều.
Để giải quyết cả hai vấn đề, tôi đã thêm một trình ghi vào log4go để xuất trực tiếp ra màn hình. Người ta dự định sử dụng FileLog và SocketLog làm chương trình phụ trợ và vẫn đưa chúng vào trong cấu trúc. Theo cách này, ứng dụng gỡ lỗi và chương trình sản xuất có thể sử dụng cùng một thư viện ghi nhật ký. Hiệu suất đo được giảm nhẹ. Tôi không biết ColorLog hoạt động như thế nào trên Windows, tôi sẽ nói về nó sau.
Trong log4go, bạn có thể tắt đầu ra màn hình bằng cách gọi SetOutput(nil) và thiết lập out = nil.
Xác định hàm gọi - tốn kém.
Câu này được chú thích trong tệp nguồn nhật ký và log4go cũng gọi hàm runtime.Caller(skip int) để lấy tên tệp nguồn và số dòng. Nó đắt tiền - nó tiêu tốn CPU. Nên tắt tính năng này trong môi trường sản xuất, log.SetSkip(-1). Nếu bạn muốn đóng gói log4go, hãy thiết lập log.SetSkip(log.GetSkip()+1) .
Tối ưu hóa định dạng.
Trên thực tế, đây chính là chủ đề của bài viết này.
Đầu ra nhật ký không thể tránh việc in ngày và giờ. Trong môi trường Linux, micro giây và có thể cả múi giờ cũng phải được in. pattlog.go của log4go được sử dụng để hoàn thành các tác vụ này.
- Có một cơ chế bộ nhớ đệm được cập nhật mỗi giây một lần. rất đẹp.
- Sử dụng rộng rãi hàm định dạng chuỗi - fmt.Sprintf.
- Trả về một chuỗi. Trình soạn thảo thường hỗ trợ []byte. Thực hiện thêm một lần chuyển đổi nữa.
- Mỗi lần bytes.Splite sẽ chia chuỗi định dạng thành []][]byte bằng ký tự %.
Một hàm itoa giá rẻ được cung cấp trong nhật ký.
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
hàm itoa(buf *[]byte, i
số nguyên
, rộng
số nguyên
) {
var b [20]byte
bp := len(b) - 1
vì
tôi >= 10 || rộng > 1 {
rộng--
q := tôi / 10
b[bp] = byte(
'0'
+ i - q*10)
bp--
tôi = q
}
b[bp] = byte(
'0'
+ tôi)
*buf = thêm(*buf, b[bp:]...)
}
|
Sử dụng hàm này để thay thế các hàm định dạng chuỗi cho ngày và giờ. Sử dụng []byte thay vì string.
Đánh giá chuẩn Log4go trước khi tối ưu hóa.
?
1
2
3
4
5
|
BenchmarkFormatLogRecord-4 300000 4480 ns/op
BenchmarkConsoleLog-4 1000000 1748 ns/op
BenchmarkConsoleNotLogged-4 20000000 97,5 ns/op
BenchmarkConsoleUtilLog-4 300000 3496 ns/op
BenchmarkConsoleUtilNotLog-4 20000000 104 ns/op
|
Sau khi tối ưu hóa:
?
1
2
3
4
|
BenchmarkFormatLogRecord-4 1000000 1443 ns/op
BenchmarkConsoleLog-4 2000000 982 ns/op
BenchmarkConsoleUtilLog-4 500000 3242 ns/op
BenchmarkConsoleUtilNotLog-4 30000000 48,4 ns/op
|
Định dạng ngày và giờ chỉ mất 1/3 thời gian.
In thông tin chưa định dạng chỉ mất một nửa thời gian.
BenchmarkConsoleUtilLog gọi runtime.Caller, định dạng thông tin và thêm thời gian để xuất thông tin ra màn hình.
Định dạng chuỗi - tương đối tốn kém.
Tóm tắt.
Trên đây là toàn bộ nội dung bài viết này, hy vọng nội dung bài viết này có giá trị tham khảo nhất định cho việc học tập hoặc công tác của bạn. Nếu có thắc mắc gì, bạn có thể để lại lời nhắn để trao đổi. Cảm ơn sự ủng hộ của bạn.
Liên kết gốc: http://www.cnblogs.com/ccpaging/p/8125265.html.
Cuối cùng, bài viết này về tối ưu hóa đầu ra nhật ký của golang log4go đã kết thúc. Nếu bạn muốn biết thêm về tối ưu hóa đầu ra nhật ký của golang log4go, vui lòng tìm kiếm các bài viết CFSDN hoặc tiếp tục duyệt các bài viết liên quan. Tôi hy vọng bạn sẽ ủng hộ blog của tôi trong tương lai! .
Tôi là một lập trình viên xuất sắc, rất giỏi!