performance - 在 init 或处理函数中读取模板?

标签 performance http go template-engine

我正在为网站编写一个基本服务器。现在我面临一个(对我来说)困难的性能问题。是不是在init()函数中读取模板文件比较好?

// Initialize all pages of website
func init(){
 indexPageData, err := ioutil.ReadFile("./tpl/index.tpl")
 check(err)
}

还是在 http.HandlerFunc 中?

func index(w http.ResponseWriter, req *http.Request){
  indexPageData, err := ioutil.ReadFile("./tpl/index.tpl")
  check(err)
  indexPageTpl := template.Must(template.New("index").Parse(string(indexPageData)))
  indexPageTpl.Execute(w, "test")
}

我认为在第一个例子中,服务器启动后你不需要访问磁盘并提高请求的性能。
但是在开发过程中我想刷新浏览器并查看新内容。这可以通过第二个示例来完成。

有人有最先进的解决方案吗?或者从性能的角度来看,什么是正确的?

最佳答案

让我们分析一下性能:

我们将您的第一个解决方案命名为a(略有变化,见下文),将您的第二个解决方案命名为b

一个请求:
a: 单盘访问
b: 单盘访问

十个请求:
a: 单盘访问
b: 十次磁盘访问

10 000 000 个请求:
a: 单盘访问
b:10 000 000 次磁盘访问(这很慢)

因此,您的第一个解决方案的性能更好。但是您对最新数据的担忧呢?来自 func (t *Template) Execute(wr io.Writer, data interface{}) error 的文档:

Execute applies a parsed template to the specified data object, writing the output to wr. If an error occurs executing the template or writing its output, execution stops, but partial results may already have been written to the output writer. A template may be executed safely in parallel.

那么,发生的事情是这样的:

  1. 你从磁盘读取了一个模板
  2. 将文件解析成模板
  3. 您选择用来填空的数据
  4. 您使用该数据执行模板,结果写入io.Writer

您的数据与您选择的一样是最新的。这与从磁盘重新读取模板甚至重新解析模板无关。这就是模板背后的全部理念:一次磁盘访问、一次解析、多个动态最终结果。

上面引用的文档告诉我们另一件事:

A template may be executed safely in parallel.

这非常有用,因为如果您有多个并行请求,您的 http.HandlerFunc 是并行运行的。

那么,现在该怎么办呢?
读取模板文件一次
解析模板一次,
为每个请求执行模板

我不确定你是否应该在 init() 函数中读取和解析,因为至少 Must 可以 panic(并且不要使用一些相关的,硬编码路径在那里!) - 我会尝试在更受控的环境中这样做,例如提供一个函数(如 New())来创建服务器的新实例并在其中执行这些操作。

编辑:我重新阅读了您的问题,我可能误解了您:

如果模板本身仍在开发中,那么是的,您必须在每次请求时阅读它以获得最新结果。这比每次更改模板都重新启动服务器更方便。对于生产,模板应该是固定的,只有数据应该改变。

对不起,如果我误会了你。

关于performance - 在 init 或处理函数中读取模板?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32578718/

相关文章:

http - 将工作的curl请求转换为HTTP

http - 从 Go 到 CouchDB 的大型 PUT 请求

go - 如何在 GO 中生成混合源和汇编列表?

java - 开发 Java Web 应用程序最有效的方法是什么?或者更具体地说,比如 Wicket 应用程序?

c# - 在 C# 中,double 比 float 快吗?

javascript - 什么决定了 Jquery 中弹出图像的边距变化量

http - 怎么测试dns-prefetch和preconnect的效果

javascript - 在node.js中接收非HTTP请求

c - 如何优化这段代码?

golang递归函数如何检查返回值?