<p>I've asked this multiple times, hopefully will got better luck here.
The original question was asked on StackOverflow, but received only one answer (not a bad one, but it didn't solve a problem).
I won't reproduce it here (if anyone wants it code <a href="http://stackoverflow.com/questions/31361745/slow-performance-of-html-template-in-go-lang-any-workaround/31367138#31367138">here's the link</a>).</p>
<p>The question is as stated in title. I've created a blog page just to test go's templating engine, was stress testing it with loader.io.
The page simply constructs an array of 100 items with one-line title and contents. Then, in a template, I {{ range }} over this data.</p>
<p><a href="http://stackoverflow.com/questions/31361745/slow-performance-of-html-template-in-go-lang-any-workaround/31367138#31367138">Here's the code again</a>.</p>
<p>Yes, I've refined the code as proposed in an answer there, but that gave totally 0% gain in performance.</p>
<p>I was impressed with how "Hello World" example beats other languages. But this one just went to the toilet. And it's so simple.</p>
<p>Please don't tell this isn't a "real-world-application-example-be-more-realistic-blah-blah". Come on, this is among most realistic examples of what the web pages are built on. I don't talk about raw inside performance here, but the simple output abilities of Go / html/template.</p>
<p>I really liked Go and really want to find out any ways can I achieve great performance that Go does inside - on the outside!</p>
<hr/>**评论:**<br/><br/>albatr0s: <pre><p>Doing</p>
<pre><code>tmpl.Execute(w, p)
</code></pre>
<p>instead of</p>
<pre><code>tmpl.ExecuteTemplate(w, "index.html", p)
</code></pre>
<p>avoids a lock and makes the benchmark finish (in my case).</p></pre>uui83: <pre><p>I'm already doing like that in all recent tests, no gain at all.</p></pre>albatr0s: <pre><p>I tested using <em>ab</em> and without that change the benchmarks didn't finish. After applying that change the test finished <em>most</em> of the times. I couldn't find the cause.</p></pre>pierrrre: <pre><p>html/template does escaping. The generated html code is safe. It's slower.</p>
<p><a href="https://golang.org/pkg/html/template/">https://golang.org/pkg/html/template/</a></p></pre>uui83: <pre><p>I know, there are, as well, lots of PHP templating and "fully secure" libraries that produce the same result in terms of performance, not sure about security though. I wasn't into this kind of thing before, just wrote everything with straight htmlspecialchars() and so far everything was fine. Just discovered html/template has an ability to set a variable as known-safe through its' type, though that doesn't work for me (don't know why), using text/template instead and escaping "danger" variables helps and keeps performance at least at PHP level.</p></pre>Mteigers: <pre><p>Most PHP renderers are also writing a cache. By time it hits a user large portions of it are static. </p></pre>funny_falcon: <pre><p>I found one compiled html template engine <a href="http://hackersome.com/p/mgutz/razor" rel="nofollow">http://hackersome.com/p/mgutz/razor</a> . Try it. It should be much faster.</p>
<p>Other options to try <a href="https://github.com/avelino/awesome-go#template-engines" rel="nofollow">https://github.com/avelino/awesome-go#template-engines</a></p>
<p><del>Other reason why php is fast: it renders html almost directly to socket (i.e. it doesn't buffer whole result by default).</del></p></pre>funny_falcon: <pre><p><a href="https://github.com/benbjohnson/ego" rel="nofollow">https://github.com/benbjohnson/ego</a></p></pre>no1youknowz: <pre><p>is there a way of doing the same with golang? that is not buffering the whole result?</p></pre>funny_falcon: <pre><p><a href="https://github.com/benbjohnson/ego" rel="nofollow">https://github.com/benbjohnson/ego</a> - try it.</p></pre>no1youknowz: <pre><blockquote>
<p>Unlike other runtime-based templating languages, ego does not support ad hoc templates. All templates must be generated before compile time.</p>
</blockquote>
<p>This is the reason why I asked my question. I saw the other link. </p>
<p>All my templates are dynamic.</p>
<p>Don't presume next time.</p></pre>funny_falcon: <pre><p>Well, it looks like I am completely mistaken: Template.Execute accepts io.Writer, so that it writes to the socket.</p></pre>no1youknowz: <pre><p>Great, thanks for the confirmation.</p></pre>uui83: <pre><p>Thanks! Gonna test in a few hours.</p></pre>uui83: <pre><p><a href="https://github.com/sipin/gorazor" rel="nofollow">gorazor</a> totally rocks! I now can include real Go code in them as well. Though compiled templates makes an additional layer of time wasted on their compile process (sure this can be automated).</p>
<p>Just <a href="https://loader.io/reports/f02cc395ac2373b8436e319c0184aa0e/results/531534cd6f5a9bf777ea05086d30a9a0" rel="nofollow">hit 160k</a> with them on my initial machine, now that's higher than PHP7. Great :)</p>
<p>And for the upgraded machine (2 cores, 4 gb) the result <a href="http://ldr.io/1TDrl5R" rel="nofollow">hit 300k</a> with 90ms average. Later I noticed that was with 1 core only. <- WOW.</p>
<p>But to mention, nginx was automatically using 2 workers and they used almost one whole core, so I think it wouldn't be a good idea to use GOMAXPROCS=2 in this certain case.</p>
<p>After PHP development & deployment process here it will be a bit tougher, but might get used to it. Hopefully reflect and text/html/template packages will improve with time...</p>
<p>BTW. After a few tests on Go, the app stays with 30-40% memory used and that isn't gonna be freed, why is it so? And how can I avoid situations when the process is killed because "out of memory" efficiently (e.g. I may try to stress test the app more hard in future).</p></pre>uui83: <pre><p>For more dramatic comparison. Upgraded test machine to 2 cores and 4 gb RAM. Tested on same "blog". Results for PHP7:
- 295k out of 300k successful responses over 1 min (5k cc/s), average latency 300ms</p>
<p>Go (using GOMAXPROCS=2, and using text/template this time cause it fails to deliver with html/template):
- 120k, average latency 4000ms</p>
<p><strong>UPD.</strong> See my <a href="https://www.reddit.com/r/golang/comments/3d6j42/why_is_htmltemplate_so_slow/ct4s9oi" rel="nofollow">comment</a> after using compiled templates.</p></pre>no1youknowz: <pre><p>I would really like to see your go code. Just in case you are doing something wrong. I would have thought golang being much faster than php 7. </p>
<p>Also how you are testing as well. ab, seige, etc?</p></pre>uui83: <pre><p>Loader.io, you can try it for free with up to 10k cc/s.
<a href="http://pastebin.com/q6Ky4gt3" rel="nofollow">This is the Go code</a></p>
<p>Golang is faster, when I don't output anything (don't use text/template).</p></pre>elithrar_: <pre><p>Just to add to my love of artificial benchmarking tools, I see 6.2k/req/s with GOMAXPROCS=4 and <code>html/template</code> with the example down-thread on an i7-4771, SSD, OS X. Available RAM inconsequential for this. Using <code>wrk -c 100 -d 5m -t 4 http://localhost:8888/</code> - external services can have a lot of variance.</p>
<p>I can't test the PHP code as it only appears to be a snippet based on the <code>Route::</code> and <code>View::</code> classes.</p></pre>uui83: <pre><p>For the PHP results pretty much everything needed to be tuned, /etc/sysctl.conf, nginx workers and php-fpm.conf (ondemand 100 children, process_idle_timeout 5s and max_requests 5000). Then I've discovered Go and here you go.</p>
<p>I use DO droplets (they have good network) and so far testing different things for about a month with loader, there were no problems with the service at both ends. I didn't test with ab/wrk/siege cause I'm on Windows and they work like broken here. But I'll try other machine later.</p></pre>elithrar_: <pre><p>Can I assume that nginx is caching responses that haven't changed? That's common behaviour (and Go can benefit from it as well).</p>
<p>I also think that's the first time in your thread(s) that you've mentioned the tuned nginx configuration. </p></pre>uui83: <pre><p>Yes, but nginx configuration is the one I use for about a month, it just uses auto workers and raises worker_rlimit_nofile (80k), as well as worker connections (40k). I didn't change anything about nginx for both Go and PHP (same goes for kernel).</p>
<p>Of course I didn't cached anything from Go/PHP as well, that's just not right. You might want to see <a href="https://www.reddit.com/r/golang/comments/3d6j42/why_is_htmltemplate_so_slow/ct4s9oi" rel="nofollow">results with compiled templates</a>.</p>
<p>If you need something from configurations, I can share, I test everything on a 512mb 1 core droplet and did a lot on tuning for past 1-2 months to get PHP work like a beast.</p></pre>iX6kNcrS: <pre><p>Just out of curiosity, what happens when $data['posts'] is different every time.</p></pre>uui83: <pre><p>By the way, I've tried mt_rand(0, 100000), it's the same. Without opcache, however, it's definitely slower (2x). But why on Earth would I switch opcache off...</p></pre>elithrar_: <pre><p>Out of curiosity: what does your PHP code look like? (i.e. post it, including mentions of any notable packages/templating libraries)</p></pre>uui83: <pre><p><a href="http://pastebin.com/fZXvnt7r" rel="nofollow">Here it is</a>
No additional packages or templating engines, just a simple router and manual escaping of what I really need (perhaps in this case I don't even need it, added to test if things go bad).</p></pre>elithrar_: <pre><p>Although it may not be the root cause, there is a big difference between what PHP's <code>htmlspecialchars</code> does and what Go's <code>html/template</code> does - see here: <a href="http://js-quasis-libraries-and-repl.googlecode.com/svn/trunk/safetemplate.html#problem_definition" rel="nofollow">http://js-quasis-libraries-and-repl.googlecode.com/svn/trunk/safetemplate.html#problem_definition</a> (<a href="/u/pierrrre" rel="nofollow">/u/pierrrre</a> touched on this in another comment)</p></pre>uui83: <pre><p>Tl;dr, I trust the security model of this package but it seems a bit overwhelming, especially when I feel some data should be defined as known-safe. As for now, using text/template produces roughly the same result as PHP does (70k+, though tbh, latest PHP7 benchmarks raised its' result up to 90k+ but that doesn't matter since it's already not those 5k for Go - probably there's some other, more lightweight way to fill this array like in PHP because at first sight, in Go, it was a bit hard for me to fill it without knowing the language, but building structs was a total fun).</p></pre>no1youknowz: <pre><p>Read, but didnt understand.</p>
<p>Are you saying, that PHP 7 is faster than Golang?</p></pre>funny_falcon: <pre><p>He says that PHP 7 is faster than Golang when you need to render html without any other sophisticated work.</p>
<p>To be more precise: he says that PHP7 (which is a huge and very optimized library for rendering unsafe html) is faster than Golang's standard library's package html/template, which is made to be simple to implement and simple and safe to use.</p>
<p>With certain level of optimisation for concrete kind of task any language could be faster than other language, which is not optimized for concrete task.</p></pre>uui83: <pre><p>Yes I'm talking about templates / rendering only.</p></pre>uui83: <pre><p>I tried to set Title, Content as template.HTML in my Post struct but everything seems the same. Is this a right way to explicitly set a variable as known-safe while still using html/template or I'm doing it wrong again? ...</p></pre>TheMerovius: <pre><p>Yes, that's the right way</p></pre>
这是一个分享于 的资源,其中的信息可能已经有所发展或是发生改变。
入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889
- 请尽量让自己的回复能够对别人有帮助
- 支持 Markdown 格式, **粗体**、~~删除线~~、
`单行代码`
- 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
- 图片支持拖拽、截图粘贴等方式上传