mirror of
https://github.com/evennia/evennia.git
synced 2026-03-18 13:56:30 +01:00
235 lines
16 KiB
HTML
235 lines
16 KiB
HTML
|
|
|
|||
|
|
<!DOCTYPE html>
|
|||
|
|
|
|||
|
|
<html>
|
|||
|
|
<head>
|
|||
|
|
<meta charset="utf-8" />
|
|||
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" /><meta name="generator" content="Docutils 0.17.1: http://docutils.sourceforge.net/" />
|
|||
|
|
|
|||
|
|
<title>Profiling — Evennia 0.9.5 documentation</title>
|
|||
|
|
<link rel="stylesheet" href="_static/nature.css" type="text/css" />
|
|||
|
|
<link rel="stylesheet" href="_static/pygments.css" type="text/css" />
|
|||
|
|
<script id="documentation_options" data-url_root="./" src="_static/documentation_options.js"></script>
|
|||
|
|
<script src="_static/jquery.js"></script>
|
|||
|
|
<script src="_static/underscore.js"></script>
|
|||
|
|
<script src="_static/doctools.js"></script>
|
|||
|
|
<script src="_static/language_data.js"></script>
|
|||
|
|
<script async="async" src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.7/latest.js?config=TeX-AMS-MML_HTMLorMML"></script>
|
|||
|
|
<script type="text/x-mathjax-config">MathJax.Hub.Config({"tex2jax": {"processClass": "tex2jax_process|mathjax_process|math|output_area"}})</script>
|
|||
|
|
<link rel="shortcut icon" href="_static/favicon.ico"/>
|
|||
|
|
<link rel="index" title="Index" href="genindex.html" />
|
|||
|
|
<link rel="search" title="Search" href="search.html" />
|
|||
|
|
</head><body>
|
|||
|
|
<div class="related" role="navigation" aria-label="related navigation">
|
|||
|
|
<h3>Navigation</h3>
|
|||
|
|
<ul>
|
|||
|
|
<li class="right" style="margin-right: 10px">
|
|||
|
|
<a href="genindex.html" title="General Index"
|
|||
|
|
accesskey="I">index</a></li>
|
|||
|
|
<li class="right" >
|
|||
|
|
<a href="py-modindex.html" title="Python Module Index"
|
|||
|
|
>modules</a> |</li>
|
|||
|
|
<li class="nav-item nav-item-0"><a href="index.html">Evennia 0.9.5</a> »</li>
|
|||
|
|
<li class="nav-item nav-item-this"><a href="">Profiling</a></li>
|
|||
|
|
</ul>
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
<div class="document">
|
|||
|
|
<div class="documentwrapper">
|
|||
|
|
<div class="bodywrapper">
|
|||
|
|
<div class="body" role="main">
|
|||
|
|
|
|||
|
|
<section class="tex2jax_ignore mathjax_ignore" id="profiling">
|
|||
|
|
<h1>Profiling<a class="headerlink" href="#profiling" title="Permalink to this headline">¶</a></h1>
|
|||
|
|
<p><em>This is considered an advanced topic mainly of interest to server developers.</em></p>
|
|||
|
|
<section id="introduction">
|
|||
|
|
<h2>Introduction<a class="headerlink" href="#introduction" title="Permalink to this headline">¶</a></h2>
|
|||
|
|
<p>Sometimes it can be useful to try to determine just how efficient a particular piece of code is, or
|
|||
|
|
to figure out if one could speed up things more than they are. There are many ways to test the
|
|||
|
|
performance of Python and the running server.</p>
|
|||
|
|
<p>Before digging into this section, remember Donald Knuth’s <a class="reference external" href="https://en.wikipedia.org/wiki/Program_optimization#When_to_optimize">words of
|
|||
|
|
wisdom</a>:</p>
|
|||
|
|
<blockquote>
|
|||
|
|
<div><p><em>[…]about 97% of the time: Premature optimization is the root of all evil</em>.</p>
|
|||
|
|
</div></blockquote>
|
|||
|
|
<p>That is, don’t start to try to optimize your code until you have actually identified a need to do
|
|||
|
|
so. This means your code must actually be working before you start to consider optimization.
|
|||
|
|
Optimization will also often make your code more complex and harder to read. Consider readability
|
|||
|
|
and maintainability and you may find that a small gain in speed is just not worth it.</p>
|
|||
|
|
</section>
|
|||
|
|
<section id="simple-timer-tests">
|
|||
|
|
<h2>Simple timer tests<a class="headerlink" href="#simple-timer-tests" title="Permalink to this headline">¶</a></h2>
|
|||
|
|
<p>Python’s <code class="docutils literal notranslate"><span class="pre">timeit</span></code> module is very good for testing small things. For example, in order to test if it
|
|||
|
|
is faster to use a <code class="docutils literal notranslate"><span class="pre">for</span></code> loop or a list comprehension you could use the following code:</p>
|
|||
|
|
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span> <span class="kn">import</span> <span class="nn">timeit</span>
|
|||
|
|
<span class="c1"># Time to do 1000000 for loops</span>
|
|||
|
|
<span class="n">timeit</span><span class="o">.</span><span class="n">timeit</span><span class="p">(</span><span class="s2">"for i in range(100):</span><span class="se">\n</span><span class="s2"> a.append(i)"</span><span class="p">,</span> <span class="n">setup</span><span class="o">=</span><span class="s2">"a = []"</span><span class="p">)</span>
|
|||
|
|
<span class="o"><<<</span> <span class="mf">10.70982813835144</span>
|
|||
|
|
<span class="c1"># Time to do 1000000 list comprehensions</span>
|
|||
|
|
<span class="n">timeit</span><span class="o">.</span><span class="n">timeit</span><span class="p">(</span><span class="s2">"a = [i for i in range(100)]"</span><span class="p">)</span>
|
|||
|
|
<span class="o"><<<</span> <span class="mf">5.358283996582031</span>
|
|||
|
|
</pre></div>
|
|||
|
|
</div>
|
|||
|
|
<p>The <code class="docutils literal notranslate"><span class="pre">setup</span></code> keyword is used to set up things that should not be included in the time measurement,
|
|||
|
|
like <code class="docutils literal notranslate"><span class="pre">a</span> <span class="pre">=</span> <span class="pre">[]</span></code> in the first call.</p>
|
|||
|
|
<p>By default the <code class="docutils literal notranslate"><span class="pre">timeit</span></code> function will re-run the given test 1000000 times and returns the <em>total
|
|||
|
|
time</em> to do so (so <em>not</em> the average per test). A hint is to not use this default for testing
|
|||
|
|
something that includes database writes - for that you may want to use a lower number of repeats
|
|||
|
|
(say 100 or 1000) using the <code class="docutils literal notranslate"><span class="pre">number=100</span></code> keyword.</p>
|
|||
|
|
</section>
|
|||
|
|
<section id="using-cprofile">
|
|||
|
|
<h2>Using cProfile<a class="headerlink" href="#using-cprofile" title="Permalink to this headline">¶</a></h2>
|
|||
|
|
<p>Python comes with its own profiler, named cProfile (this is for cPython, no tests have been done
|
|||
|
|
with <code class="docutils literal notranslate"><span class="pre">pypy</span></code> at this point). Due to the way Evennia’s processes are handled, there is no point in
|
|||
|
|
using the normal way to start the profiler (<code class="docutils literal notranslate"><span class="pre">python</span> <span class="pre">-m</span> <span class="pre">cProfile</span> <span class="pre">evennia.py</span></code>). Instead you start the
|
|||
|
|
profiler through the launcher:</p>
|
|||
|
|
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>evennia --profiler start
|
|||
|
|
</pre></div>
|
|||
|
|
</div>
|
|||
|
|
<p>This will start Evennia with the Server component running (in daemon mode) under cProfile. You could
|
|||
|
|
instead try <code class="docutils literal notranslate"><span class="pre">--profile</span></code> with the <code class="docutils literal notranslate"><span class="pre">portal</span></code> argument to profile the Portal (you would then need to
|
|||
|
|
<a class="reference internal" href="Start-Stop-Reload.html"><span class="doc std std-doc">start the Server separately</span></a>).</p>
|
|||
|
|
<p>Please note that while the profiler is running, your process will use a lot more memory than usual.
|
|||
|
|
Memory usage is even likely to climb over time. So don’t leave it running perpetually but monitor it
|
|||
|
|
carefully (for example using the <code class="docutils literal notranslate"><span class="pre">top</span></code> command on Linux or the Task Manager’s memory display on
|
|||
|
|
Windows).</p>
|
|||
|
|
<p>Once you have run the server for a while, you need to stop it so the profiler can give its report.
|
|||
|
|
Do <em>not</em> kill the program from your task manager or by sending it a kill signal - this will most
|
|||
|
|
likely also mess with the profiler. Instead either use <code class="docutils literal notranslate"><span class="pre">evennia.py</span> <span class="pre">stop</span></code> or (which may be even
|
|||
|
|
better), use <code class="docutils literal notranslate"><span class="pre">@shutdown</span></code> from inside the game.</p>
|
|||
|
|
<p>Once the server has fully shut down (this may be a lot slower than usual) you will find that
|
|||
|
|
profiler has created a new file <code class="docutils literal notranslate"><span class="pre">mygame/server/logs/server.prof</span></code>.</p>
|
|||
|
|
</section>
|
|||
|
|
<section id="analyzing-the-profile">
|
|||
|
|
<h2>Analyzing the profile<a class="headerlink" href="#analyzing-the-profile" title="Permalink to this headline">¶</a></h2>
|
|||
|
|
<p>The <code class="docutils literal notranslate"><span class="pre">server.prof</span></code> file is a binary file. There are many ways to analyze and display its contents,
|
|||
|
|
all of which has only been tested in Linux (If you are a Windows/Mac user, let us know what works).</p>
|
|||
|
|
<p>We recommend the
|
|||
|
|
<a class="reference external" href="http://www.vrplumber.com/programming/runsnakerun/">Runsnake</a> visualizer to see the processor usage
|
|||
|
|
of different processes in a graphical form. For more detailed listing of usage time, you can use
|
|||
|
|
<a class="reference external" href="http://kcachegrind.sourceforge.net/html/Home.html">KCachegrind</a>. To make KCachegrind work with
|
|||
|
|
Python profiles you also need the wrapper script
|
|||
|
|
<a class="reference external" href="https://pypi.python.org/pypi/pyprof2calltree/">pyprof2calltree</a>. You can get pyprof2calltree via
|
|||
|
|
<code class="docutils literal notranslate"><span class="pre">pip</span></code> whereas KCacheGrind is something you need to get via your package manager or their homepage.</p>
|
|||
|
|
<p>How to analyze and interpret profiling data is not a trivial issue and depends on what you are
|
|||
|
|
profiling for. Evennia being an asynchronous server can also confuse profiling. Ask on the mailing
|
|||
|
|
list if you need help and be ready to be able to supply your <code class="docutils literal notranslate"><span class="pre">server.prof</span></code> file for comparison,
|
|||
|
|
along with the exact conditions under which it was obtained.</p>
|
|||
|
|
</section>
|
|||
|
|
<section id="the-dummyrunner">
|
|||
|
|
<h2>The Dummyrunner<a class="headerlink" href="#the-dummyrunner" title="Permalink to this headline">¶</a></h2>
|
|||
|
|
<p>It is difficult to test “actual” game performance without having players in your game. For this
|
|||
|
|
reason Evennia comes with the <em>Dummyrunner</em> system. The Dummyrunner is a stress-testing system: a
|
|||
|
|
separate program that logs into your game with simulated players (aka “bots” or “dummies”). Once
|
|||
|
|
connected these dummies will semi-randomly perform various tasks from a list of possible actions.
|
|||
|
|
Use <code class="docutils literal notranslate"><span class="pre">Ctrl-C</span></code> to stop the Dummyrunner.</p>
|
|||
|
|
<blockquote>
|
|||
|
|
<div><p>Warning: You should not run the Dummyrunner on a production database. It will spawn many objects
|
|||
|
|
and also needs to run with general permissions.</p>
|
|||
|
|
</div></blockquote>
|
|||
|
|
<p>To launch the Dummyrunner, first start your server normally (with or without profiling, as above).
|
|||
|
|
Then start a new terminal/console window and active your virtualenv there too. In the new terminal,
|
|||
|
|
try to connect 10 dummy players:</p>
|
|||
|
|
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>evennia --dummyrunner 10
|
|||
|
|
</pre></div>
|
|||
|
|
</div>
|
|||
|
|
<p>The first time you do this you will most likely get a warning from Dummyrunner. It will tell you to
|
|||
|
|
copy an import string to the end of your settings file. Quit the Dummyrunner (<code class="docutils literal notranslate"><span class="pre">Ctrl-C</span></code>) and follow
|
|||
|
|
the instructions. Restart Evennia and try <code class="docutils literal notranslate"><span class="pre">evennia</span> <span class="pre">--dummyrunner</span> <span class="pre">10</span></code> again. Make sure to remove that
|
|||
|
|
extra settings line when running a public server.</p>
|
|||
|
|
<p>The actions perform by the dummies is controlled by a settings file. The default Dummyrunner
|
|||
|
|
settings file is <code class="docutils literal notranslate"><span class="pre">evennia/server/server/profiling/dummyrunner_settings.py</span></code> but you shouldn’t modify
|
|||
|
|
this directly. Rather create/copy the default file to <code class="docutils literal notranslate"><span class="pre">mygame/server/conf/</span></code> and modify it there. To
|
|||
|
|
make sure to use your file over the default, add the following line to your settings file:</p>
|
|||
|
|
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="n">DUMMYRUNNER_SETTINGS_MODULE</span> <span class="o">=</span> <span class="s2">"server/conf/dummyrunner_settings.py"</span>
|
|||
|
|
</pre></div>
|
|||
|
|
</div>
|
|||
|
|
<blockquote>
|
|||
|
|
<div><p>Hint: Don’t start with too many dummies. The Dummyrunner defaults to taxing the server much more
|
|||
|
|
intensely than an equal number of human players. A good dummy number to start with is 10-100.</p>
|
|||
|
|
</div></blockquote>
|
|||
|
|
<p>Once you have the dummyrunner running, stop it with <code class="docutils literal notranslate"><span class="pre">Ctrl-C</span></code>.</p>
|
|||
|
|
<p>Generally, the dummyrunner system makes for a decent test of general performance; but it is of
|
|||
|
|
course hard to actually mimic human user behavior. For this, actual real-game testing is required.</p>
|
|||
|
|
</section>
|
|||
|
|
</section>
|
|||
|
|
|
|||
|
|
|
|||
|
|
<div class="clearer"></div>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
<div class="sphinxsidebar" role="navigation" aria-label="main navigation">
|
|||
|
|
<div class="sphinxsidebarwrapper">
|
|||
|
|
<p class="logo"><a href="index.html">
|
|||
|
|
<img class="logo" src="_static/evennia_logo.png" alt="Logo"/>
|
|||
|
|
</a></p>
|
|||
|
|
<div id="searchbox" style="display: none" role="search">
|
|||
|
|
<h3 id="searchlabel">Quick search</h3>
|
|||
|
|
<div class="searchformwrapper">
|
|||
|
|
<form class="search" action="search.html" method="get">
|
|||
|
|
<input type="text" name="q" aria-labelledby="searchlabel" />
|
|||
|
|
<input type="submit" value="Go" />
|
|||
|
|
</form>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
<script>$('#searchbox').show(0);</script>
|
|||
|
|
<p><h3><a href="index.html">Table of Contents</a></h3>
|
|||
|
|
<ul>
|
|||
|
|
<li><a class="reference internal" href="#">Profiling</a><ul>
|
|||
|
|
<li><a class="reference internal" href="#introduction">Introduction</a></li>
|
|||
|
|
<li><a class="reference internal" href="#simple-timer-tests">Simple timer tests</a></li>
|
|||
|
|
<li><a class="reference internal" href="#using-cprofile">Using cProfile</a></li>
|
|||
|
|
<li><a class="reference internal" href="#analyzing-the-profile">Analyzing the profile</a></li>
|
|||
|
|
<li><a class="reference internal" href="#the-dummyrunner">The Dummyrunner</a></li>
|
|||
|
|
</ul>
|
|||
|
|
</li>
|
|||
|
|
</ul>
|
|||
|
|
|
|||
|
|
<div role="note" aria-label="source link">
|
|||
|
|
<!--h3>This Page</h3-->
|
|||
|
|
<ul class="this-page-menu">
|
|||
|
|
<li><a href="_sources/Profiling.md.txt"
|
|||
|
|
rel="nofollow">Show Page Source</a></li>
|
|||
|
|
</ul>
|
|||
|
|
</div><h3>Links</h3>
|
|||
|
|
<ul>
|
|||
|
|
<li><a href="https://www.evennia.com">Home page</a> </li>
|
|||
|
|
<li><a href="https://github.com/evennia/evennia">Evennia Github</a> </li>
|
|||
|
|
<li><a href="http://games.evennia.com">Game Index</a> </li>
|
|||
|
|
<li><a href="http://webchat.freenode.net/?channels=evennia&uio=MT1mYWxzZSY5PXRydWUmMTE9MTk1JjEyPXRydWUbb">IRC</a> -
|
|||
|
|
<a href="https://discord.gg/NecFePw">Discord</a> -
|
|||
|
|
<a href="https://groups.google.com/forum/#%21forum/evennia">Forums</a>
|
|||
|
|
</li>
|
|||
|
|
<li><a href="http://evennia.blogspot.com/">Evennia Dev blog</a> </li>
|
|||
|
|
</ul>
|
|||
|
|
<h3>Versions</h3>
|
|||
|
|
<ul>
|
|||
|
|
<li><a href="../1.0-dev/index.html">1.0-dev (develop branch)</a></li>
|
|||
|
|
<li><a href="Profiling.html">0.9.5 (v0.9.5 branch)</a></li>
|
|||
|
|
</ul>
|
|||
|
|
|
|||
|
|
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
<div class="clearer"></div>
|
|||
|
|
</div>
|
|||
|
|
<div class="related" role="navigation" aria-label="related navigation">
|
|||
|
|
<h3>Navigation</h3>
|
|||
|
|
<ul>
|
|||
|
|
<li class="right" style="margin-right: 10px">
|
|||
|
|
<a href="genindex.html" title="General Index"
|
|||
|
|
>index</a></li>
|
|||
|
|
<li class="right" >
|
|||
|
|
<a href="py-modindex.html" title="Python Module Index"
|
|||
|
|
>modules</a> |</li>
|
|||
|
|
<li class="nav-item nav-item-0"><a href="index.html">Evennia 0.9.5</a> »</li>
|
|||
|
|
<li class="nav-item nav-item-this"><a href="">Profiling</a></li>
|
|||
|
|
</ul>
|
|||
|
|
</div>
|
|||
|
|
<div class="footer" role="contentinfo">
|
|||
|
|
© Copyright 2020, The Evennia developer community.
|
|||
|
|
Created using <a href="https://www.sphinx-doc.org/">Sphinx</a> 3.2.1.
|
|||
|
|
</div>
|
|||
|
|
</body>
|
|||
|
|
</html>
|