Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/http/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Performance 慢日志包_Performance_Http_Go_Logging - Fatal编程技术网

Performance 慢日志包

Performance 慢日志包,performance,http,go,logging,Performance,Http,Go,Logging,为什么Gologpackage会让我的http API慢得这么厉害?有那么慢吗 下面是我的路由器示例,使用而不使用日志记录: package main import ( "fmt" "log" "net/http" "time" "github.com/julienschmidt/httprouter" ) func main() { hand

为什么Go
log
package会让我的http API慢得这么厉害?有那么慢吗

下面是我的路由器示例,使用而不使用日志记录:

package main

import (
    "fmt"
    "log"
    "net/http"
    "time"

    "github.com/julienschmidt/httprouter"
)

func main() {
    handler := httprouter.New()
    handler.GET("/hello", f)
    http.ListenAndServe(fmt.Sprintf(":%d", 8080), handler)
}

func f(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
    w.WriteHeader(http.StatusOK)
    fmt.Fprint(w, "world")
}
使用基准测试该端点,我得到以下结果:

$wrk-t1-d1s-c100http://localhost:8080/hello
正在运行1s测试@http://localhost:8080/hello
1个螺纹和100个接头
线程统计平均标准偏差最大+/-标准偏差
延迟1.15ms 197.55us 2.84ms 80.02%
要求/秒84.58k 6.15k 99.01k 80.00%
83904个1.01秒请求,读取9.68MB
请求/秒:83380.37
传输/秒:9.62MB
当我为日志添加中间件时:

package main

import (
    "fmt"
    "log"
    "net/http"
    "time"

    "github.com/julienschmidt/httprouter"
)

func main() {
    handler := httprouter.New()
    handler.GET("/hello", logger(f))
    fmt.Println("httprouter")
    http.ListenAndServe(fmt.Sprintf(":%d", 8080), handler)
}

func logger(next httprouter.Handle) httprouter.Handle {
    return func(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
        start := time.Now()
        next(w, r, ps)
        elapsed := time.Since(start)
        log.Printf("%s | %s | %s | %d\n", time.Now().Format(time.RFC3339), r.Method, r.URL.Path, elapsed)
    }
}

func f(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
    w.WriteHeader(http.StatusOK)
    fmt.Fprint(w, "world")
}

速度降低到4倍:

$ wrk -t1 -d1s -c100 http://localhost:8080/hello
Running 1s test @ http://localhost:8080/hello
  1 threads and 100 connections
  Thread Stats   Avg      Stdev     Max   +/- Stdev
    Latency     5.25ms    4.34ms  26.47ms   60.23%
    Req/Sec    20.51k     2.19k   24.28k    70.00%
  20449 requests in 1.01s, 2.36MB read
Requests/sec:  20330.66
Transfer/sec:      2.35MB
我在本地测试了它:

MacBook Pro 13inches
2 GHz Quad-Core Intel Core i5
Memory 16GB

I use default Go max proc without modifying anything after installed.

log
程序包有那么慢吗?有什么改进的建议吗?

这个答案总结了对这个问题的评论

  • 使用缓冲io
  • 从一个goroutine写入,以减少来自其他日志goroutine的阻塞
代码如下:

type writer chan []byte

func (w writer) Write(p []byte) (int, error) {
    w <- append(([]byte)(nil), p...)
    return len(p), nil
}

func writePump(w writer) {
    bw := bufio.NewWriter(os.Stderr)
    for p := range w {
        bw.Write(p)

        // Slurp up buffered messages in flush. This ensures
        // timely output.
        n := len(w)
        for i := 0; i < n; i++ {
            bw.Write(<-w)
        }
        bw.Flush()
    }
}

默认情况下,日志包直接写入stderr。在缓冲写入程序中交换以提高性能:
bw:=buffo.NewWriter(os.Stderr);延迟bw.Flush();log.SetOutput(bw)
@velkor是正确的。使用缓冲写入程序。此外,您编写的中间件还做了大量额外的工作,如日志记录、
time.Now
time.Since
,等等,这些都是性能下降的原因。我认为您应该记录
已用时间
而不是
time.Now().Format(time.rfc339)
来获取写入响应所用的时间(持续时间)。@shmsr我认为调用time.Now()和time.Since不会使性能降低那么多。显然,它直接登录到os.Stderr。每个日志输出都与互斥锁同步。因此,如果您在任何地方都有相同的互斥,那么您必须在每次登录时获取它。想象一下这对你的工作有什么影响concurrency@WhitePanther我的意思是使用一个go例程来记录在缓冲通道上循环的日志,这样日志函数基本上会将日志推送到通道,并且不会对API响应时间造成瓶颈;这个imo应该有用。你能详细说明为什么我们需要额外的“咕噜…”吗?
w := make(writer, 16) // adjust capacity to meet your needs
go writePump(w)
log.SetOutput(w)