【问题标题】:pprof profile with julienschmidtrouter and benchmarks not profiling handler带有 julienschmidtrouter 的 pprof 配置文件和基准不分析处理程序
【发布时间】:2018-05-07 05:46:50
【问题描述】:

我正在尝试分析我编写的 Web 服务器,但我的 pprof 不包含有关处理程序 func 的任何数据。
我正在使用 julienschmidt 的 httprouter package,并且想简单地对我的一个处理程序进行基准测试并查看 pprof 配置文件。对于基准测试,我使用的是go-wrk

我这样设置我的网络服务器和 pprof:

// Configure the server
server := &http.Server{
    Addr:    ":4000",
    Handler: router,
}

go func() {
    log.Println(http.ListenAndServe(":6060", nil))
}()

// Start the server
err = server.ListenAndServe()
if err != nil {
    panic(err)
}

路由器初始化如下:

// Create the httprouter
router := httprouter.New()
// Register all handlers
router.GET("/entities/:type/map", h.UseHandler(&h.ApiGetEntitiesMapRequest{}, p))

我的处理程序看起来像这样:

func (req ApiGetEntitiesMapRequest) Handle(r *http.Request, hrp httprouter.Params, p Params) (interface{}, error) {
    test := make([]string, 0)
    for i := 0; i < 1000; i++ {
        test = append(test, "1")
        test = append(test, "2")
        // Ensure pprof has some time to collect its data
        time.Sleep(10)
    }
    return test, nil
}

这个处理程序只是一个测试,我在其中动态地将很多元素附加到一个切片中。这样做的原因是,我想测试这些动态分配是否在 pprof 的堆配置文件中表示。

现在,我所做的是:

请求有效,我的基准测试也正确报告了所有内容。但是,当我在 pprof 终端中键入 png 时,我得到了这个 graph。

该图不包含有关我的处理程序的任何信息以及我在处理程序中所做的昂贵的堆分配。我做错了什么?

【问题讨论】:

    标签: go webserver benchmarking pprof


    【解决方案1】:

    所以,我终于找到了问题所在!

    如果您使用自定义多路复用器来处理您的请求,您需要将 pprof 处理程序注册到您的多路复用器中,以便获得正确的分析:

    router.HandlerFunc(http.MethodGet, "/debug/pprof/", pprof.Index)
    router.HandlerFunc(http.MethodGet, "/debug/pprof/cmdline", pprof.Cmdline)
    router.HandlerFunc(http.MethodGet, "/debug/pprof/profile", pprof.Profile)
    router.HandlerFunc(http.MethodGet, "/debug/pprof/symbol", pprof.Symbol)
    router.HandlerFunc(http.MethodGet, "/debug/pprof/trace", pprof.Trace)
    router.Handler(http.MethodGet, "/debug/pprof/goroutine", pprof.Handler("goroutine"))
    router.Handler(http.MethodGet, "/debug/pprof/heap", pprof.Handler("heap"))
    router.Handler(http.MethodGet,"/debug/pprof/threadcreate", pprof.Handler("threadcreate"))
    router.Handler(http.MethodGet,"/debug/pprof/block", pprof.Handler("block"))
    

    现在我得到了我想要的结果!

    【讨论】:

    • 我已经这样做了,但是我看到了以下问题:go tool pprof localhost:8000/debug/pprof/profile Fetching profile from localhost:8000/debug/pprof/profile Please wait... (30s) http fetch localhost:8000/debug/pprof/profile: Get localhost:8000/debug/pprof/profile : EOF 我的服务器在 8000 上运行
    • 你用的是哪种多路复用器?
    • 稍微偏离主题:我相信您可以通过使用以下代码来避免对所有这些处理程序进行硬编码:router.Handler(http.MethodGet, "/debug/pprof/:item", http.DefaultServeMux)(其中:item 用作 pprof 将忽略的虚拟占位符变量)。
    • @MihaiTodor 你测试过这个吗?您的声明不会错过注册 pprof.Index 等吗?
    • @skaldesh 在抱怨我 2 年前的建议不起作用之前,您是否使用旧版本的 julienschmidt/httprouter 对其进行了测试?似乎对该软件包进行了一些向后不兼容的更改,并且我的原始代码在最新版本中无法按预期工作。我能够让它像这样工作:router.Handler(http.MethodGet, "/debug/pprof/*item", http.DefaultServeMux)。试一试,看看它是否适合你。
    猜你喜欢
    • 2023-03-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-06-23
    • 1970-01-01
    • 2019-09-23
    • 2023-04-01
    • 1970-01-01
    相关资源
    最近更新 更多