Created
September 14, 2017 11:51
-
-
Save samuelcolvin/8362662a9c3aade012bc2e107024287c to your computer and use it in GitHub Desktop.
aiohttp async template performance
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
~ 0 23ms ➤ wrk -t 10 -c 100 -d 10 http://localhost:8000/ # master | |
Running 10s test @ http://localhost:8000/ | |
10 threads and 100 connections | |
Thread Stats Avg Stdev Max +/- Stdev | |
Latency 166.16ms 8.92ms 242.51ms 97.42% | |
Req/Sec 62.68 28.98 101.00 56.98% | |
5973 requests in 10.01s, 219.57MB read | |
Requests/sec: 596.69 | |
Transfer/sec: 21.93MB | |
~ 0 10.02s ➤ wrk -t 10 -c 100 -d 10 http://localhost:8000/ # enable_async=False | |
Running 10s test @ http://localhost:8000/ | |
10 threads and 100 connections | |
Thread Stats Avg Stdev Max +/- Stdev | |
Latency 166.76ms 8.97ms 243.25ms 95.75% | |
Req/Sec 62.09 29.77 101.00 56.58% | |
5954 requests in 10.01s, 218.87MB read | |
Requests/sec: 594.52 | |
Transfer/sec: 21.85MB | |
~ 0 10.03s ➤ wrk -t 10 -c 100 -d 10 http://localhost:8000/ # enable_async=True | |
Running 10s test @ http://localhost:8000/ | |
10 threads and 100 connections | |
Thread Stats Avg Stdev Max +/- Stdev | |
Latency 446.02ms 42.20ms 536.24ms 96.04% | |
Req/Sec 30.18 23.44 90.00 72.06% | |
2195 requests in 10.01s, 80.69MB read | |
Requests/sec: 219.19 | |
Transfer/sec: 8.06MB | |
~ 0 10.03s ➤ wrk -t 10 -c 100 -d 10 http://localhost:8000/ # enable_async=True with StreamResponse | |
Running 10s test @ http://localhost:8000/ | |
10 threads and 100 connections | |
Thread Stats Avg Stdev Max +/- Stdev | |
Latency 1.07s 548.73ms 1.95s 57.89% | |
Req/Sec 6.01 3.35 10.00 53.54% | |
99 requests in 10.01s, 6.83MB read | |
Socket errors: connect 0, read 0, write 0, timeout 80 | |
Requests/sec: 9.89 | |
Transfer/sec: 698.38KB | |
~ 0 10.03s ➤ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<html lang="en"> | |
<head> | |
<meta charset="utf-8"> | |
{% if responsive and not responsive.request_desktop %} | |
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=0"/> | |
{% endif %} | |
{% block extra_meta %} | |
<meta name="description" content="Tutoring Business Management Software"> | |
<meta name="author" content="TutorCruncher"> | |
<meta http-equiv="X-UA-Compatible" content="IE=edge"> | |
{% endblock %} | |
<title>{{ title }}</title> | |
</head> | |
<body> | |
{% block body %}{% endblock %} | |
<script async src='https://www.google-analytics.com/analytics.js'></script> | |
</body> | |
</html> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{% extends 'index.jinja' %} | |
{% block body %} | |
{% if not bar %} | |
<div class="section" id="basics"> | |
<h2>Basics<a class="headerlink" href="#basics" title="Permalink to this headline">¶</a></h2> | |
<p>Jinja2 uses a central object called the template <a class="reference internal" href="#jinja2.Environment" title="jinja2.Environment"><code class="xref py py-class docutils literal"><span class="pre">Environment</span></code></a>. | |
Instances of this class are used to store the configuration and global objects, | |
and are used to load templates from the file system or other locations. | |
Even if you are creating templates from strings by using the constructor of | |
<a class="reference internal" href="#jinja2.Template" title="jinja2.Template"><code class="xref py py-class docutils literal"><span class="pre">Template</span></code></a> class, an environment is created automatically for you, | |
albeit a shared one.</p> | |
{% endif %} | |
<p>Most applications will create one <a class="reference internal" href="#jinja2.Environment" title="jinja2.Environment"><code class="xref py py-class docutils literal"><span class="pre">Environment</span></code></a> object on application | |
initialization and use that to load templates. In some cases however, it’s | |
useful to have multiple environments side by side, if different configurations | |
are in use.</p> | |
<p>The simplest way to configure Jinja2 to load templates for your application | |
looks roughly like this:</p> | |
<div class="highlight-default"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">jinja2</span> <span class="k">import</span> <span class="n">Environment</span><span class="p">,</span> <span class="n">PackageLoader</span><span class="p">,</span> <span class="n">select_autoescape</span> | |
<span class="n">env</span> <span class="o">=</span> <span class="n">Environment</span><span class="p">(</span> | |
<span class="n">loader</span><span class="o">=</span><span class="n">PackageLoader</span><span class="p">(</span><span class="s1">'yourapplication'</span><span class="p">,</span> <span class="s1">'templates'</span><span class="p">),</span> | |
<span class="n">autoescape</span><span class="o">=</span><span class="n">select_autoescape</span><span class="p">([</span><span class="s1">'html'</span><span class="p">,</span> <span class="s1">'xml'</span><span class="p">])</span> | |
<span class="p">)</span> | |
</pre></div> | |
</div> | |
<p>This will create a template environment with the default settings and a | |
loader that looks up the templates in the <cite>templates</cite> folder inside the | |
<cite>yourapplication</cite> python package. Different loaders are available | |
and you can also write your own if you want to load templates from a | |
database or other resources. This also enables autoescaping for HTML and | |
XML files.</p> | |
<p>To load a template from this environment you just have to call the | |
<code class="xref py py-meth docutils literal"><span class="pre">get_template()</span></code> method which then returns the loaded <a class="reference internal" href="#jinja2.Template" title="jinja2.Template"><code class="xref py py-class docutils literal"><span class="pre">Template</span></code></a>:</p> | |
<div class="highlight-default"><div class="highlight"><pre><span></span><span class="n">template</span> <span class="o">=</span> <span class="n">env</span><span class="o">.</span><span class="n">get_template</span><span class="p">(</span><span class="s1">'mytemplate.html'</span><span class="p">)</span> | |
</pre></div> | |
</div> | |
<p>To render it with some variables, just call the <code class="xref py py-meth docutils literal"><span class="pre">render()</span></code> method:</p> | |
<div class="highlight-default"><div class="highlight"><pre><span></span><span class="nb">print</span> <span class="n">template</span><span class="o">.</span><span class="n">render</span><span class="p">(</span><span class="n">the</span><span class="o">=</span><span class="s1">'variables'</span><span class="p">,</span> <span class="n">go</span><span class="o">=</span><span class="s1">'here'</span><span class="p">)</span> | |
</pre></div> | |
</div> | |
<p>Using a template loader rather than passing strings to <a class="reference internal" href="#jinja2.Template" title="jinja2.Template"><code class="xref py py-class docutils literal"><span class="pre">Template</span></code></a> | |
or <a class="reference internal" href="#jinja2.Environment.from_string" title="jinja2.Environment.from_string"><code class="xref py py-meth docutils literal"><span class="pre">Environment.from_string()</span></code></a> has multiple advantages. Besides being | |
a lot easier to use it also enables template inheritance.</p> | |
<div class="admonition-notes-on-autoescaping admonition"> | |
<p class="first admonition-title">Notes on Autoescaping</p> | |
<p class="last">In future versions of Jinja2 we might enable autoescaping by default | |
for security reasons. As such you are encouraged to explicitly | |
configure autoescaping now instead of relying on the default.</p> | |
</div> | |
</div> | |
<p>Length: {{ data|length }}</p> | |
<ul> | |
{% for v in data %} | |
<li> | |
{% for word in v %}{{ word }} {% endfor %} | |
</li> | |
{% endfor %} | |
</ul> | |
{% endblock %} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import random | |
from pathlib import Path | |
import jinja2 | |
from aiohttp import web | |
import aiohttp_jinja2 | |
WORDS = Path('/usr/share/dict/words').read_text().split() | |
random.seed(a=1) | |
DATA = [ | |
random.choices(WORDS, k=random.randint(10, max(12, v))) for v in range(100) | |
] | |
@aiohttp_jinja2.template('page.jinja') | |
async def handle(request): | |
return { | |
'title': 'Testing', | |
'data': DATA | |
} | |
app = web.Application() | |
template_dir = Path(__file__).resolve().parent / 'templates' | |
aiohttp_jinja2.setup(app, enable_async=True, loader=jinja2.FileSystemLoader(str(template_dir))) | |
app.router.add_get('/', handle) | |
web.run_app(app, port=8000) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment