如何解决将HTTP响应写入一个临时字节
[从评论中复制作为答案]
只需使用不是来自标准库的可用池来缓冲缓冲区。这看起来很有效(可以在godoc上搜索一些其他方法):
http://godoc.org/github.com/oxtoacart/bpool
无论大小如何,您可能还应该看到通过减少垃圾收集器压力而增加了吞吐量。
解决方法
我一直在进行一些性能分析和基准测试,以优化向临时文件的写操作,bytes.Buffer
以捕获来自的任何错误template.ExecuteTemplate
。
具体来说,我们正在写入缓冲区,检查是否有错误,如果没有,则写出到http.ResponseWriter
。但是,问题在于临时缓冲区的请求开销有些明显:
- 启用剖析时约为6.2k req / s-27.6k-> 21.4k,禁用时为29k-> 24k;
- 每个请求的延迟增加9毫秒(40毫秒-> 49毫秒)。
当然,21k req / s仍然是很多请求,但是性能为22%。打击也是一个相当大的影响。
func renderTemplate(w http.ResponseWriter,name string,data map[string]interface{}) error {
// Ensure the template exists in the map.
tmpl,ok := templates[name]
if !ok {
return ErrTemplateDoesNotExist
}
// Create a buffer to temporarily write to and check if any errors were encountered.
buf := bytes.NewBuffer(make([]byte,10000))
err := tmpl.ExecuteTemplate(buf,"base",data)
if err != nil {
return err
}
// Set the header and write the buffer to the http.ResponseWriter
w.Header().Set("Content-Type","text/html; charset=utf-8")
buf.WriteTo(w)
return nil
}
10K缓冲区大小是我 大多数 响应的典型最大页面大小的粗略估计,尽管我尚未在少数页面上进行测试。大于缓冲区大小的响应通常会导致性能降低20%。
是否有更好的方法在 每个
请求中写入临时缓冲区?另一位地鼠指出了即将推出的sync.Pool在Go
1.3中,但是我不确定从哪里开始写。
新增
:目前使用http://godoc.org/github.com/oxtoacart/bpool可以以每个请求36ms的速度产生33k
req / s:
var bufpool *bpool.BufferPool
func renderTemplate(w http.ResponseWriter,data map[string]interface{}) error {
...
buf := bufpool.Get()
err := tmpl.ExecuteTemplate(buf,"text/html; charset=utf-8")
buf.WriteTo(w)
bufpool.Put(buf)
return nil
}
func init() {
bufpool = bpool.NewBufferPool(48)
}
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。