英文:
It takes too much time when using "template" package to generate a dynamic web page to client in Golang
问题
使用template
包生成动态网页发送给客户端时,速度非常慢。
以下是测试代码,使用的是golang 1.4.1版本:
http.Handle("/js/", (http.FileServer(http.Dir(webpath))))
http.Handle("/css/", (http.FileServer(http.Dir(webpath))))
http.Handle("/img/", (http.FileServer(http.Dir(webpath))))
http.HandleFunc("/test", TestHandler)
func TestHandler(w http.ResponseWriter, r *http.Request) {
Log.Info("Entering TestHandler ...")
r.ParseForm()
filename := NiConfig.webpath + "/test.html"
t, err := template.ParseFiles(filename)
if err != nil {
Log.Error("template.ParseFiles err = %v", err)
}
t.Execute(w, nil)
}
根据日志,我发现在t.Execute(w, nil)
这一行大约花费了3秒的时间,我不知道为什么会花费这么长的时间。我还尝试了使用Apache服务器测试test.html
,它的响应非常快。
英文:
It is so slow when using template
package to generate a dynamic web page to client.
Testing code as below, golang 1.4.1
http.Handle("/js/", (http.FileServer(http.Dir(webpath))))
http.Handle("/css/", (http.FileServer(http.Dir(webpath))))
http.Handle("/img/", (http.FileServer(http.Dir(webpath))))
http.HandleFunc("/test", TestHandler)
func TestHandler(w http.ResponseWriter, r *http.Request) {
Log.Info("Entering TestHandler ...")
r.ParseForm()
filename := NiConfig.webpath + "/test.html"
t, err := template.ParseFiles(filename)
if err != nil {
Log.Error("template.ParseFiles err = %v", err)
}
t.Execute(w, nil)
}
According to the log, I found that it took about 3 seconds in t.Execute(w, nil)
, I do not know why it uses so much time. I also tried Apache server to test test.html
, it responded very fast.
答案1
得分: 17
每次提供请求时,你不应该解析模板!
读取文件、解析内容和构建模板都需要花费相当长的时间。而且,由于模板不会改变(变化的部分应该是参数!),你只需要读取和解析一次模板即可。此外,每次提供请求时解析和创建模板会在内存中生成大量的值,然后被丢弃(因为它们不会被重用),这给垃圾回收器增加了额外的工作量。
在应用程序启动时解析模板,将其存储在一个变量中,只有在请求到达时才执行模板。例如:
var t *template.Template
func init() {
filename := NiConfig.webpath + "/test.html"
t = template.Must(template.ParseFiles(filename))
http.HandleFunc("/test", TestHandler)
}
func TestHandler(w http.ResponseWriter, r *http.Request) {
Log.Info("进入TestHandler...")
// 模板已准备好,只需执行它
if err := t.Execute(w, nil); err != nil {
log.Printf("无法执行模板:%v", err)
}
}
英文:
You should not parse templates every time you serve a request!
There is a significant time delay to read a file, parse its content and build the template. Also since templates do not change (varying parts should be parameters!) you only have to read and parse a template once.
Also parsing and creating the template each time when serving a request generates lots of values in memory which are then thrown away (because they are not reused) giving additional work for the garbage collector.
Parse the templates when your application starts, store it in a variable, and you only have to execute the template when a request comes in. For example:
var t *template.Template
func init() {
filename := NiConfig.webpath + "/test.html"
t = template.Must(template.ParseFiles(filename))
http.HandleFunc("/test", TestHandler)
}
func TestHandler(w http.ResponseWriter, r *http.Request) {
Log.Info("Entering TestHandler ...")
// Template is ready, just Execute it
if err := t.Execute(w, nil); err != nil {
log.Printf("Failed to execute template: %v", err)
}
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论