mirror of
https://github.com/kataras/iris.git
synced 2025-12-18 02:17:05 +00:00
Add View Engine Benchmarks: https://github.com/kataras/iris/tree/master/_benchmarks/view
This commit is contained in:
@@ -1,3 +1,4 @@
|
||||
# Benchmarks
|
||||
|
||||
Moved to <https://github.com/kataras/server-benchmarks#benchmarks>.
|
||||
- [HTTP/2 Benchmarks](https://github.com/kataras/server-benchmarks#benchmarks)
|
||||
- [View Engine Benchmarks](./view)
|
||||
|
||||
56
_benchmarks/view/README.md
Normal file
56
_benchmarks/view/README.md
Normal file
@@ -0,0 +1,56 @@
|
||||
# View Engine Benchmarks
|
||||
|
||||
Benchmark between all 8 supported template parsers.
|
||||
|
||||
Amber, Ace and Pug parsers minifies the template before render. So, to have a fair benchmark, we must make sure that the byte amount of the total response body is exactly the same across all. Therefore, all other template files are minified too.
|
||||
|
||||

|
||||
|
||||
> Last updated: Oct 1, 2020 at 12:46pm (UTC)
|
||||
|
||||
## System
|
||||
|
||||
| | |
|
||||
|----|:---|
|
||||
| Processor | Intel(R) Core(TM) i7-8750H CPU @ 2.20GHz |
|
||||
| RAM | 15.85 GB |
|
||||
| OS | Microsoft Windows 10 Pro |
|
||||
| [Bombardier](https://github.com/codesenberg/bombardier) | v1.2.4 |
|
||||
| [Go](https://golang.org) | go1.15.2 |
|
||||
|
||||
## Terminology
|
||||
|
||||
**Name** is the name of the framework(or router) used under a particular test.
|
||||
|
||||
**Reqs/sec** is the avg number of total requests could be processed per second (the higher the better).
|
||||
|
||||
**Latency** is the amount of time it takes from when a request is made by the client to the time it takes for the response to get back to that client (the smaller the better).
|
||||
|
||||
**Throughput** is the rate of production or the rate at which data are transferred (the higher the better, it depends from response length (body + headers).
|
||||
|
||||
**Time To Complete** is the total time (in seconds) the test completed (the smaller the better).
|
||||
|
||||
## Results
|
||||
|
||||
### Test:Template Layout, Partial and Data
|
||||
|
||||
📖 Fires 1000000 requests with 125 concurrent clients. It receives HTML response. The server handler sets some template **data** and renders a template file which consists of a **layout** and a **partial** footer.
|
||||
|
||||
| Name | Language | Reqs/sec | Latency | Throughput | Time To Complete |
|
||||
|------|:---------|:---------|:--------|:-----------|:-----------------|
|
||||
| [Amber](./amber) | Go |125698 |0.99ms |44.67MB |7.96s |
|
||||
| [Blocks](./blocks) | Go |123974 |1.01ms |43.99MB |8.07s |
|
||||
| [Django](./django) | Go |118831 |1.05ms |42.17MB |8.41s |
|
||||
| [Handlebars](./handlebars) | Go |101214 |1.23ms |35.91MB |9.88s |
|
||||
| [Pug](./pug) | Go |89002 |1.40ms |31.81MB |11.24s |
|
||||
| [Ace](./ace) | Go |64782 |1.93ms |22.98MB |15.44s |
|
||||
| [HTML](./html) | Go |53918 |2.32ms |19.13MB |18.55s |
|
||||
| [Jet](./jet) | Go |4829 |25.88ms |1.71MB |207.07s |
|
||||
|
||||
## How to Run
|
||||
|
||||
```sh
|
||||
$ go get -u github.com/kataras/server-benchmarks
|
||||
$ go get -u github.com/codesenberg/bombardier
|
||||
$ server-benchmarks --wait-run=3s -o ./results
|
||||
```
|
||||
24
_benchmarks/view/ace/main.go
Normal file
24
_benchmarks/view/ace/main.go
Normal file
@@ -0,0 +1,24 @@
|
||||
package main
|
||||
|
||||
import "github.com/kataras/iris/v12"
|
||||
|
||||
func main() {
|
||||
app := iris.New()
|
||||
// By default Ace engine minifies the template before render.
|
||||
app.RegisterView(iris.Ace("./views", ".ace").SetIndent(""))
|
||||
|
||||
app.Get("/", index)
|
||||
|
||||
app.Listen(":8080")
|
||||
}
|
||||
|
||||
func index(ctx iris.Context) {
|
||||
data := iris.Map{
|
||||
"Title": "Page Title",
|
||||
"FooterText": "Footer contents",
|
||||
"Message": "Main contents",
|
||||
}
|
||||
|
||||
ctx.ViewLayout("layouts/main")
|
||||
ctx.View("index", data)
|
||||
}
|
||||
2
_benchmarks/view/ace/views/index.ace
Normal file
2
_benchmarks/view/ace/views/index.ace
Normal file
@@ -0,0 +1,2 @@
|
||||
h1 Index Body
|
||||
h3 Message: {{.Message}}
|
||||
8
_benchmarks/view/ace/views/layouts/main.ace
Normal file
8
_benchmarks/view/ace/views/layouts/main.ace
Normal file
@@ -0,0 +1,8 @@
|
||||
= doctype html
|
||||
html
|
||||
head
|
||||
title {{.Title}}
|
||||
body
|
||||
{{ yield }}
|
||||
footer
|
||||
= include partials/footer.ace .
|
||||
2
_benchmarks/view/ace/views/partials/footer.ace
Normal file
2
_benchmarks/view/ace/views/partials/footer.ace
Normal file
@@ -0,0 +1,2 @@
|
||||
h3 Footer Partial
|
||||
h4 {{.FooterText}}
|
||||
26
_benchmarks/view/amber/main.go
Normal file
26
_benchmarks/view/amber/main.go
Normal file
@@ -0,0 +1,26 @@
|
||||
package main
|
||||
|
||||
import "github.com/kataras/iris/v12"
|
||||
|
||||
func main() {
|
||||
app := iris.New()
|
||||
// By default Amber engine minifies the template before render.
|
||||
app.RegisterView(iris.Amber("./views", ".amber"))
|
||||
|
||||
app.Get("/", index)
|
||||
|
||||
app.Listen(":8080")
|
||||
}
|
||||
|
||||
func index(ctx iris.Context) {
|
||||
data := iris.Map{
|
||||
"Title": "Page Title",
|
||||
"FooterText": "Footer contents",
|
||||
"Message": "Main contents",
|
||||
}
|
||||
|
||||
// On Amber this is ignored: ctx.ViewLayout("layouts/main")
|
||||
// Layouts are only rendered from inside the index page itself
|
||||
// using the "extends" keyword.
|
||||
ctx.View("index", data)
|
||||
}
|
||||
5
_benchmarks/view/amber/views/index.amber
Normal file
5
_benchmarks/view/amber/views/index.amber
Normal file
@@ -0,0 +1,5 @@
|
||||
extends layouts/main.amber
|
||||
|
||||
block content
|
||||
h1 Index Body
|
||||
h3 Message: #{Message}
|
||||
8
_benchmarks/view/amber/views/layouts/main.amber
Normal file
8
_benchmarks/view/amber/views/layouts/main.amber
Normal file
@@ -0,0 +1,8 @@
|
||||
doctype html
|
||||
html
|
||||
head
|
||||
title #{Title}
|
||||
body
|
||||
block content
|
||||
footer
|
||||
#{render("partials/footer.amber", $)}
|
||||
2
_benchmarks/view/amber/views/partials/footer.amber
Normal file
2
_benchmarks/view/amber/views/partials/footer.amber
Normal file
@@ -0,0 +1,2 @@
|
||||
h3 Footer Partial
|
||||
h4 #{FooterText}
|
||||
26
_benchmarks/view/blocks/main.go
Normal file
26
_benchmarks/view/blocks/main.go
Normal file
@@ -0,0 +1,26 @@
|
||||
package main
|
||||
|
||||
import "github.com/kataras/iris/v12"
|
||||
|
||||
func main() {
|
||||
app := iris.New()
|
||||
app.RegisterView(iris.Blocks("./views", ".html"))
|
||||
// Note, in Blocks engine, layouts
|
||||
// are used by their base names, the
|
||||
// blocks.LayoutDir(layoutDir) defaults to "./layouts".
|
||||
|
||||
app.Get("/", index)
|
||||
|
||||
app.Listen(":8080")
|
||||
}
|
||||
|
||||
func index(ctx iris.Context) {
|
||||
data := iris.Map{
|
||||
"Title": "Page Title",
|
||||
"FooterText": "Footer contents",
|
||||
"Message": "Main contents",
|
||||
}
|
||||
|
||||
ctx.ViewLayout("main")
|
||||
ctx.View("index", data)
|
||||
}
|
||||
1
_benchmarks/view/blocks/views/index.html
Normal file
1
_benchmarks/view/blocks/views/index.html
Normal file
@@ -0,0 +1 @@
|
||||
<h1>Index Body</h1><h3>Message: {{.Message}}</h3>
|
||||
1
_benchmarks/view/blocks/views/layouts/main.html
Normal file
1
_benchmarks/view/blocks/views/layouts/main.html
Normal file
@@ -0,0 +1 @@
|
||||
<!DOCTYPE html><html><head><title>{{.Title}}</title></head><body>{{ template "content" . }}<footer>{{ partial "partials/footer" .}}</footer></body></html>
|
||||
1
_benchmarks/view/blocks/views/partials/footer.html
Normal file
1
_benchmarks/view/blocks/views/partials/footer.html
Normal file
@@ -0,0 +1 @@
|
||||
<h3>Footer Partial</h3><h4>{{.FooterText}}</h4>
|
||||
BIN
_benchmarks/view/chart.png
Normal file
BIN
_benchmarks/view/chart.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 9.9 KiB |
25
_benchmarks/view/django/main.go
Normal file
25
_benchmarks/view/django/main.go
Normal file
@@ -0,0 +1,25 @@
|
||||
package main
|
||||
|
||||
import "github.com/kataras/iris/v12"
|
||||
|
||||
func main() {
|
||||
app := iris.New()
|
||||
app.RegisterView(iris.Django("./views", ".html"))
|
||||
|
||||
app.Get("/", index)
|
||||
|
||||
app.Listen(":8080")
|
||||
}
|
||||
|
||||
func index(ctx iris.Context) {
|
||||
data := iris.Map{
|
||||
"Title": "Page Title",
|
||||
"FooterText": "Footer contents",
|
||||
"Message": "Main contents",
|
||||
}
|
||||
|
||||
// On Django this is ignored: ctx.ViewLayout("layouts/main")
|
||||
// Layouts are only rendered from inside the index page itself
|
||||
// using the "extends" keyword.
|
||||
ctx.View("index", data)
|
||||
}
|
||||
1
_benchmarks/view/django/views/index.html
Normal file
1
_benchmarks/view/django/views/index.html
Normal file
@@ -0,0 +1 @@
|
||||
{% extends "layouts/main.html" %}{% block content %}<h1>Index Body</h1><h3>Message: {{Message}}</h3>{% endblock %}
|
||||
1
_benchmarks/view/django/views/layouts/main.html
Normal file
1
_benchmarks/view/django/views/layouts/main.html
Normal file
@@ -0,0 +1 @@
|
||||
<!DOCTYPE html><html><head><title>{{Title}}</title></head><body>{% block content %} {% endblock %}<footer>{% include "../partials/footer.html" %}</footer></body></html>
|
||||
1
_benchmarks/view/django/views/partials/footer.html
Normal file
1
_benchmarks/view/django/views/partials/footer.html
Normal file
@@ -0,0 +1 @@
|
||||
<h3>Footer Partial</h3><h4>{{FooterText}}</h4>
|
||||
23
_benchmarks/view/handlebars/main.go
Normal file
23
_benchmarks/view/handlebars/main.go
Normal file
@@ -0,0 +1,23 @@
|
||||
package main
|
||||
|
||||
import "github.com/kataras/iris/v12"
|
||||
|
||||
func main() {
|
||||
app := iris.New()
|
||||
app.RegisterView(iris.Handlebars("./views", ".html"))
|
||||
|
||||
app.Get("/", index)
|
||||
|
||||
app.Listen(":8080")
|
||||
}
|
||||
|
||||
func index(ctx iris.Context) {
|
||||
data := iris.Map{
|
||||
"Title": "Page Title",
|
||||
"FooterText": "Footer contents",
|
||||
"Message": "Main contents",
|
||||
}
|
||||
|
||||
ctx.ViewLayout("layouts/main")
|
||||
ctx.View("index", data)
|
||||
}
|
||||
1
_benchmarks/view/handlebars/views/index.html
Normal file
1
_benchmarks/view/handlebars/views/index.html
Normal file
@@ -0,0 +1 @@
|
||||
<h1>Index Body</h1><h3>Message: {{Message}}</h3>
|
||||
1
_benchmarks/view/handlebars/views/layouts/main.html
Normal file
1
_benchmarks/view/handlebars/views/layouts/main.html
Normal file
@@ -0,0 +1 @@
|
||||
<!DOCTYPE html><html><head><title>{{Title}}</title></head><body>{{ yield }}<footer>{{ render "partials/footer.html" .}}</footer></body></html>
|
||||
1
_benchmarks/view/handlebars/views/partials/footer.html
Normal file
1
_benchmarks/view/handlebars/views/partials/footer.html
Normal file
@@ -0,0 +1 @@
|
||||
<h3>Footer Partial</h3><h4>{{FooterText}}</h4>
|
||||
24
_benchmarks/view/html/main.go
Normal file
24
_benchmarks/view/html/main.go
Normal file
@@ -0,0 +1,24 @@
|
||||
package main
|
||||
|
||||
import "github.com/kataras/iris/v12"
|
||||
|
||||
func main() {
|
||||
app := iris.New()
|
||||
|
||||
app.RegisterView(iris.HTML("./views", ".html"))
|
||||
|
||||
app.Get("/", index)
|
||||
|
||||
app.Listen(":8080")
|
||||
}
|
||||
|
||||
func index(ctx iris.Context) {
|
||||
data := iris.Map{
|
||||
"Title": "Page Title",
|
||||
"FooterText": "Footer contents",
|
||||
"Message": "Main contents",
|
||||
}
|
||||
|
||||
ctx.ViewLayout("layouts/main")
|
||||
ctx.View("index", data)
|
||||
}
|
||||
1
_benchmarks/view/html/views/index.html
Normal file
1
_benchmarks/view/html/views/index.html
Normal file
@@ -0,0 +1 @@
|
||||
<h1>Index Body</h1><h3>Message: {{.Message}}</h3>
|
||||
1
_benchmarks/view/html/views/layouts/main.html
Normal file
1
_benchmarks/view/html/views/layouts/main.html
Normal file
@@ -0,0 +1 @@
|
||||
<!DOCTYPE html><html><head><title>{{.Title}}</title></head><body>{{ yield }}<footer>{{ render "partials/footer.html" }}</footer></body></html>
|
||||
1
_benchmarks/view/html/views/partials/footer.html
Normal file
1
_benchmarks/view/html/views/partials/footer.html
Normal file
@@ -0,0 +1 @@
|
||||
<h3>Footer Partial</h3><h4>{{.FooterText}}</h4>
|
||||
25
_benchmarks/view/jet/main.go
Normal file
25
_benchmarks/view/jet/main.go
Normal file
@@ -0,0 +1,25 @@
|
||||
package main
|
||||
|
||||
import "github.com/kataras/iris/v12"
|
||||
|
||||
func main() {
|
||||
app := iris.New()
|
||||
app.RegisterView(iris.Jet("./views", ".jet"))
|
||||
|
||||
app.Get("/", index)
|
||||
|
||||
app.Listen(":8080")
|
||||
}
|
||||
|
||||
func index(ctx iris.Context) {
|
||||
data := iris.Map{
|
||||
"Title": "Page Title",
|
||||
"FooterText": "Footer contents",
|
||||
"Message": "Main contents",
|
||||
}
|
||||
|
||||
// On Jet this is ignored: ctx.ViewLayout("layouts/main")
|
||||
// Layouts are only rendered from inside the index page itself
|
||||
// using the "extends" keyword.
|
||||
ctx.View("index", data)
|
||||
}
|
||||
1
_benchmarks/view/jet/views/index.jet
Normal file
1
_benchmarks/view/jet/views/index.jet
Normal file
@@ -0,0 +1 @@
|
||||
{{ extends "../layouts/main.jet" }}{{ block documentBody() }}<h1>Index Body</h1><h3>Message: {{.Message}}</h3>{{ end }}
|
||||
1
_benchmarks/view/jet/views/layouts/main.jet
Normal file
1
_benchmarks/view/jet/views/layouts/main.jet
Normal file
@@ -0,0 +1 @@
|
||||
<!DOCTYPE html><html><head><title>{{.Title}}</title></head><body>{{ yield documentBody() }}<footer>{{ include "../partials/footer.jet" . }}</footer></body></html>
|
||||
1
_benchmarks/view/jet/views/partials/footer.jet
Normal file
1
_benchmarks/view/jet/views/partials/footer.jet
Normal file
@@ -0,0 +1 @@
|
||||
<h3>Footer Partial</h3><h4>{{.FooterText}}</h4>
|
||||
26
_benchmarks/view/pug/main.go
Normal file
26
_benchmarks/view/pug/main.go
Normal file
@@ -0,0 +1,26 @@
|
||||
package main
|
||||
|
||||
import "github.com/kataras/iris/v12"
|
||||
|
||||
func main() {
|
||||
app := iris.New()
|
||||
// Ace engine minifies the template before render.
|
||||
app.RegisterView(iris.Pug("./views", ".pug"))
|
||||
|
||||
app.Get("/", index)
|
||||
|
||||
app.Listen(":8080")
|
||||
}
|
||||
|
||||
func index(ctx iris.Context) {
|
||||
data := iris.Map{
|
||||
"Title": "Page Title",
|
||||
"FooterText": "Footer contents",
|
||||
"Message": "Main contents",
|
||||
}
|
||||
|
||||
// On Pug this is ignored: ctx.ViewLayout("layouts/main")
|
||||
// Layouts are only rendered from inside the index page itself
|
||||
// using the "extends" keyword.
|
||||
ctx.View("index", data)
|
||||
}
|
||||
5
_benchmarks/view/pug/views/index.pug
Normal file
5
_benchmarks/view/pug/views/index.pug
Normal file
@@ -0,0 +1,5 @@
|
||||
extends layouts/main.pug
|
||||
|
||||
block content
|
||||
h1 Index Body
|
||||
h3 Message: {{.Message}}
|
||||
8
_benchmarks/view/pug/views/layouts/main.pug
Normal file
8
_benchmarks/view/pug/views/layouts/main.pug
Normal file
@@ -0,0 +1,8 @@
|
||||
doctype html
|
||||
html
|
||||
head
|
||||
title {{.Title}}
|
||||
body
|
||||
block content
|
||||
footer
|
||||
include ../partials/footer.pug
|
||||
2
_benchmarks/view/pug/views/partials/footer.pug
Normal file
2
_benchmarks/view/pug/views/partials/footer.pug
Normal file
@@ -0,0 +1,2 @@
|
||||
h3 Footer Partial
|
||||
h4 {{.FooterText}}
|
||||
27
_benchmarks/view/tests.yml
Normal file
27
_benchmarks/view/tests.yml
Normal file
@@ -0,0 +1,27 @@
|
||||
- Name: Template Layout, Partial and Data
|
||||
Description: >
|
||||
Fires {{.NumberOfRequests}} requests with {{.NumberOfConnections}} concurrent clients.
|
||||
It receives HTML response.
|
||||
The server handler sets some template **data** and renders a
|
||||
template file which consists of a **layout** and a **partial** footer.
|
||||
NumberOfRequests: 1000000
|
||||
NumberOfConnections: 125
|
||||
Method: GET
|
||||
URL: http://localhost:8080
|
||||
Envs:
|
||||
- Name: Ace
|
||||
Dir: ./ace
|
||||
- Name: Amber
|
||||
Dir: ./amber
|
||||
- Name: Blocks
|
||||
Dir: ./blocks
|
||||
- Name: Django
|
||||
Dir: ./django
|
||||
- Name: Handlebars
|
||||
Dir: ./handlebars
|
||||
- Name: HTML
|
||||
Dir: ./html
|
||||
- Name: Jet
|
||||
Dir: ./jet
|
||||
- Name: Pug
|
||||
Dir: ./pug
|
||||
Reference in New Issue
Block a user