| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486 |
- <!DOCTYPE html>
- <html lang="en">
- <head>
- <meta charset="utf-8">
- <meta name="viewport" content="width=device-width,initial-scale=1">
- <title>Optimizing Your Game Using Statistics :: jMonkeyEngine Docs</title>
- <link rel="canonical" href="https://wiki.jmonkeyengine.org/docs/jme3/advanced/statsview.html">
- <meta name="generator" content="Antora 2.3.3">
- <link rel="stylesheet" href="../../../_/css/site.css">
- <meta property="og:image" content="https://wiki.jmonkeyengine.org/_/img/iconx128.png">
- <meta property="og:description" content="Optimizing Your Game Using Statistics">
- <meta property="og:title" content="jMonkeyEngine Docs">
- <link rel="stylesheet" href="../../../_/css/site-extra.css">
- <link rel="stylesheet" href="../../../_/css/vendor/docsearch.min.css">
- <!-- fetched from https://cdn.jsdelivr.net/npm/docsearch.js@2/dist/cdn/docsearch.min.css -->
- <link rel="icon" href="../../../_/img/favicon.ico" type="image/x-icon">
- </head>
- <body class="article">
- <header class="header">
- <nav class="navbar">
- <div class="navbar-brand">
- <a class="navbar-item" href="https://wiki.jmonkeyengine.org">
- <img alt="" src="../../../_/img/jMonkeyDocLogo.png" height="32" type="image/x-icon">
- </a>
- <div class="navbar-item hide-for-print">
- <input type="text" placeholder="Search docs..." id="search-input"/>
- </div>
- <button class="navbar-burger" data-target="topbar-nav">
- <span></span>
- <span></span>
- <span></span>
- </button>
- </div>
- <div id="topbar-nav" class="navbar-menu">
- <div class="navbar-end">
- <div class="navbar-item theme-switch-wrapper">
- <label class="theme-switch" for="checkbox">
- <input type="checkbox" id="checkbox" />
- <div class="slider round"></div>
- </label>
- </div>
- <a class="navbar-item" href="https://github.com/jmonkeyengine/wiki">Github</a>
- </div>
- </div>
- </nav>
- </header>
- <div class="body">
- <div class="nav-container" data-component="docs" data-version="master">
- <aside class="nav">
- <div class="panels">
- <div class="nav-panel-menu is-active" data-panel="menu">
- <nav class="nav-menu">
- <h3 class="title"><a href="../../documentation.html">Docs</a></h3>
- <ul class="nav-list">
- <li class="nav-item" data-depth="0">
- <ul class="nav-list">
- <li class="nav-item" data-depth="1">
- <a class="nav-link" href="../../documentation.html">Getting Started</a>
- </li>
- <li class="nav-item" data-depth="1">
- <a class="nav-link" href="https://javadoc.jmonkeyengine.org/v3.3.2-stable">JavaDoc</a>
- </li>
- <li class="nav-item" data-depth="1">
- <button class="nav-item-toggle"></button>
- <a class="nav-link" href="../../jme3.html">jMonkeyEngine 3</a>
- <ul class="nav-list">
- <li class="nav-item" data-depth="2">
- <button class="nav-item-toggle"></button>
- <span class="nav-text">Beginner Tutorials</span>
- <ul class="nav-list">
- <li class="nav-item" data-depth="3">
- <a class="nav-link" href="../beginner/hello_simpleapplication.html">Hello SimpleApplication</a>
- </li>
- <li class="nav-item" data-depth="3">
- <a class="nav-link" href="../beginner/hello_node.html">Hello Node</a>
- </li>
- <li class="nav-item" data-depth="3">
- <a class="nav-link" href="../beginner/hello_asset.html">Hello Asset</a>
- </li>
- <li class="nav-item" data-depth="3">
- <a class="nav-link" href="../beginner/hello_main_event_loop.html">Hello Main Event Loop</a>
- </li>
- <li class="nav-item" data-depth="3">
- <a class="nav-link" href="../beginner/hello_input_system.html">Hello Input System</a>
- </li>
- <li class="nav-item" data-depth="3">
- <a class="nav-link" href="../beginner/hello_material.html">Hello Material</a>
- </li>
- <li class="nav-item" data-depth="3">
- <a class="nav-link" href="../beginner/hello_animation.html">Hello Animation</a>
- </li>
- <li class="nav-item" data-depth="3">
- <a class="nav-link" href="../beginner/hello_picking.html">Hello Picking</a>
- </li>
- <li class="nav-item" data-depth="3">
- <a class="nav-link" href="../beginner/hello_collision.html">Hello Collision</a>
- </li>
- <li class="nav-item" data-depth="3">
- <a class="nav-link" href="../beginner/hello_terrain.html">Hello Terrain</a>
- </li>
- <li class="nav-item" data-depth="3">
- <a class="nav-link" href="../beginner/hello_audio.html">Hello Audio</a>
- </li>
- <li class="nav-item" data-depth="3">
- <a class="nav-link" href="../beginner/hello_effects.html">Hello Effects</a>
- </li>
- <li class="nav-item" data-depth="3">
- <a class="nav-link" href="../beginner/hello_physics.html">Hello Physics</a>
- </li>
- </ul>
- </li>
- <li class="nav-item" data-depth="2">
- <button class="nav-item-toggle"></button>
- <span class="nav-text">Intermediate Tutorials</span>
- <ul class="nav-list">
- <li class="nav-item" data-depth="3">
- <button class="nav-item-toggle"></button>
- <span class="nav-text">Concepts</span>
- <ul class="nav-list">
- <li class="nav-item" data-depth="4">
- <a class="nav-link" href="../intermediate/best_practices.html">Best Practices</a>
- </li>
- <li class="nav-item" data-depth="4">
- <a class="nav-link" href="../intermediate/simpleapplication.html">Simple Application</a>
- </li>
- <li class="nav-item" data-depth="4">
- <a class="nav-link" href="../features.html">Features</a>
- </li>
- <li class="nav-item" data-depth="4">
- <a class="nav-link" href="../intermediate/optimization.html">Optimization</a>
- </li>
- <li class="nav-item" data-depth="4">
- <a class="nav-link" href="../faq.html">FAQ</a>
- </li>
- </ul>
- </li>
- <li class="nav-item" data-depth="3">
- <button class="nav-item-toggle"></button>
- <span class="nav-text">Math Concepts</span>
- <ul class="nav-list">
- <li class="nav-item" data-depth="4">
- <a class="nav-link" href="../math_for_dummies.html">Math For Dummies</a>
- </li>
- <li class="nav-item" data-depth="4">
- <a class="nav-link" href="../intermediate/math.html">Math</a>
- </li>
- <li class="nav-item" data-depth="4">
- <a class="nav-link" href="../math.html">More Math</a>
- </li>
- <li class="nav-item" data-depth="4">
- <a class="nav-link" href="../rotate.html">Rotate</a>
- </li>
- <li class="nav-item" data-depth="4">
- <a class="nav-link" href="../math_video_tutorials.html">Math Video Tutorials</a>
- </li>
- </ul>
- </li>
- <li class="nav-item" data-depth="3">
- <button class="nav-item-toggle"></button>
- <span class="nav-text">3D Graphics Concepts</span>
- <ul class="nav-list">
- <li class="nav-item" data-depth="4">
- <a class="nav-link" href="../intermediate/multi-media_asset_pipeline.html">Multi-Media Asset Pipeline</a>
- </li>
- <li class="nav-item" data-depth="4">
- <a class="nav-link" href="../scenegraph_for_dummies.html">Scenegraph for Dummies</a>
- </li>
- <li class="nav-item" data-depth="4">
- <a class="nav-link" href="../beginner/hellovector.html">Hello Vector</a>
- </li>
- <li class="nav-item" data-depth="4">
- <a class="nav-link" href="../terminology.html">Terminology</a>
- </li>
- <li class="nav-item" data-depth="4">
- <a class="nav-link" href="../intermediate/how_to_use_materials.html">How to Use Materials</a>
- </li>
- <li class="nav-item" data-depth="4">
- <a class="nav-link" href="../intermediate/transparency_sorting.html">Transparency and Sorting</a>
- </li>
- <li class="nav-item" data-depth="4">
- <a class="nav-link" href="../external/blender.html">Importing from Blender</a>
- </li>
- <li class="nav-item" data-depth="4">
- <a class="nav-link" href="../external/3dsmax.html">Importing from 3DS Max</a>
- </li>
- </ul>
- </li>
- </ul>
- </li>
- </ul>
- </li>
- <li class="nav-item" data-depth="1">
- <a class="nav-link" href="../../logo.html">Logo Usage</a>
- </li>
- <li class="nav-item" data-depth="1">
- <a class="nav-link" href="../../bsd_license.html">License</a>
- </li>
- <li class="nav-item" data-depth="1">
- <a class="nav-link" href="../../github_tips.html">Github Tips</a>
- </li>
- </ul>
- </li>
- <li class="nav-item" data-depth="0">
- <button class="nav-item-toggle"></button>
- <span class="nav-text">SDK</span>
- <ul class="nav-list">
- <li class="nav-item" data-depth="1">
- <a class="nav-link" href="../../sdk.html">jMonkeyEngine SDK</a>
- </li>
- </ul>
- </li>
- </ul>
- </nav>
- </div>
- <div class="nav-panel-explore" data-panel="explore">
- <div class="context">
- <span class="title">Docs</span>
- <span class="version">master</span>
- </div>
- <ul class="components">
- <li class="component is-current">
- <span class="title">Docs</span>
- <ul class="versions">
- <li class="version is-current is-latest">
- <a href="../../documentation.html">master</a>
- </li>
- </ul>
- </li>
- <li class="component">
- <span class="title">Wiki UI</span>
- <ul class="versions">
- <li class="version is-latest">
- <a href="../../../wiki-ui/index.html">master</a>
- </li>
- </ul>
- </li>
- </ul>
- </div>
- </div>
- </aside>
- </div>
- <main class="article">
- <div class="toolbar" role="navigation">
- <button class="nav-toggle"></button>
- <nav class="breadcrumbs" aria-label="breadcrumbs">
- <ul>
- <li><a href="../../documentation.html">Docs</a></li>
- <li><a href="statsview.html">Optimizing Your Game Using Statistics</a></li>
- </ul>
- </nav>
- <div class="edit-this-page"><a href="https://github.com/jMonkeyEngine/wiki/edit/master/docs/modules/ROOT/pages/jme3/advanced/statsview.adoc">Edit this Page</a></div>
- </div>
- <div class="content">
- <article class="doc">
- <h1 class="page">Optimizing Your Game Using Statistics</h1>
- <div id="preamble">
- <div class="sectionbody">
- <div class="paragraph">
- <p>When you create a SimpleApplication, you see the default StatsView and FpsView in the left corner.
- The StatsView displays object statistics that are used during development, for example for debugging and optimization.
- Below the StatsView is the FpsView that displays the frames that jMonkeyEngine can render per second.</p>
- </div>
- <div class="paragraph">
- <p>The main use case of these statistics is to find out why the application may be running slow and where to start fixing the performance.</p>
- </div>
- <div class="paragraph">
- <p>The StatsView + FpsView look like this example:</p>
- </div>
- <div class="listingblock">
- <div class="content">
- <pre class="highlightjs highlight"><code>FrameBuffers (M) = 2
- FrameBuffers (F) = 2
- FrameBuffers (S) = 2
- Textures (M) = 7
- Textures (F) = 3
- Textures (S) = 3
- Shaders (M) = 6
- Shaders (F) = 3
- Shaders (S) = 4
- Objects = 24
- Uniforms = 31
- Triangles = 582
- Vertices = 1148
- Frames per Second: 30</code></pre>
- </div>
- </div>
- </div>
- </div>
- <div class="sect1">
- <h2 id="onoff"><a class="anchor" href="#onoff"></a>On/Off</h2>
- <div class="sectionbody">
- <div class="paragraph">
- <p>You switch the StatsView on an off in the simpleInitApp() method by setting a boolean:</p>
- </div>
- <div class="listingblock">
- <div class="content">
- <pre class="highlightjs highlight"><code class="language-java hljs" data-lang="java">setDisplayFps(false); // to hide the FPS
- setDisplayStatView(false); // to hide the statistics</code></pre>
- </div>
- </div>
- </div>
- </div>
- <div class="sect1">
- <h2 id="terminology"><a class="anchor" href="#terminology"></a>Terminology</h2>
- <div class="sectionbody">
- <div class="paragraph">
- <p>Types of items counted:</p>
- </div>
- <div class="ulist">
- <ul>
- <li>
- <p>FrameBuffers: Total number of rendering surfaces used for off-screen rendering and render-to-texture functionality.</p>
- </li>
- <li>
- <p>Textures: Total number of distinct textures used in the scene.</p>
- </li>
- <li>
- <p>Shaders: Total number of shaders used for effects (shading, blur, lighting, glow, etc).</p>
- </li>
- <li>
- <p>Objects: Total number of objects in the OpenGL pipeline. That is, objects attached to the rootNode and guiNode, etc.</p>
- </li>
- <li>
- <p>Uniforms: Total number of shader uniforms. Uniforms are predefined variables used as parameters in shader calculations, containing data such as matrices, vectors, time, and colors.</p>
- </li>
- <li>
- <p>Triangles: Total number of triangles (faces) of the meshes of all objects.</p>
- </li>
- <li>
- <p>Vertices: Total number of vertices (corner points) of the meshes of all the objects.</p>
- </li>
- </ul>
- </div>
- <div class="paragraph">
- <p>Types of statistics:</p>
- </div>
- <div class="ulist">
- <ul>
- <li>
- <p><strong>(M) = Memory</strong> – Number of items currently in OpenGL memory.</p>
- </li>
- <li>
- <p>*(F) = Frame * – Number of items used by current frame (visible).</p>
- </li>
- <li>
- <p><strong>(S) = Switches</strong> – Number of items that were state switched in the last frame.</p>
- </li>
- </ul>
- </div>
- <div class="paragraph">
- <p>The StatsView does not include any Physics statistics.</p>
- </div>
- </div>
- </div>
- <div class="sect1">
- <h2 id="how-to-interpret-the-fps-when-optimizing"><a class="anchor" href="#how-to-interpret-the-fps-when-optimizing"></a>How to Interpret the FPS when Optimizing</h2>
- <div class="sectionbody">
- <div class="paragraph">
- <p>The FPS (frames per second) shows you how fast jME runs the update loop. If the FPS values goes below 30, the game slows down and runs jerky, which makes the game either frustrating or impossible to play. You need either decrease the number of operations in the update loop, or decrease memory usage (object count).</p>
- </div>
- <div class="paragraph">
- <p>If your application grows more and more sluggish, deactivate or decrease one feature set at a time: Deactivate drop shadows, physics, anti-aliasing… Try fewer light sources, fewer NPCs, fewer samples in spheres (i.e. less smooth spheres). Temporarily replace the scene (or parts of it) with a simpler test scene to check whether the scene has to many triangles, etc.</p>
- </div>
- <div class="paragraph">
- <p>Keep an eye on FPS and the StatsView and find out which element has the biggest impact on performance. This is where you start optimizing.</p>
- </div>
- </div>
- </div>
- <div class="sect1">
- <h2 id="how-to-interpret-the-statistics"><a class="anchor" href="#how-to-interpret-the-statistics"></a>How to Interpret The Statistics</h2>
- <div class="sectionbody">
- <div class="admonitionblock important">
- <table>
- <tr>
- <td class="icon">
- <i class="fa icon-important" title="Important"></i>
- </td>
- <td class="content">
- <div class="paragraph">
- <p>To interpret the numbers correctly, consider that the 14 lines of text themselves already count as 14 objects with 914 vertices. You need to subtract these values from the totals for smaller performance experiments.</p>
- </div>
- </td>
- </tr>
- </table>
- </div>
- <div class="paragraph">
- <p>What do you want to avoid?</p>
- </div>
- <div class="olist arabic">
- <ol class="arabic">
- <li>
- <p>FrameBuffers: If you don’t use any post-processing effects (FilterPostProcessor), this count should be zero. The more effects you use, the more FrameBuffers are in use. If this value is high while others are normal, and your game is sluggish, you can speed up the application by using fewer post-processing effects.</p>
- </li>
- <li>
- <p>The Object Count (Batch Count) is a very important value that indicates how many geometries were rendered in the last frame. In general, if you keep the object count around 100-200, your game will be fast and responsive. If the count is permanently higher, hand-code rules that detach remote objects, or optimize a complex multi-material scene using: <code>GeometryBatchFactory.optimize(complexNode, true);</code> or a <a href="texture_atlas.html" class="page">Texture Atlas</a>.</p>
- </li>
- <li>
- <p>Triangle Counts. If your game is sluggish and triangle (polygon) count is high, then you are rendering too many, too detailed meshes. Tell your graphic designers to create models with lower polygon counts, or use a <a href="level_of_detail.html" class="page">Level of Detail</a> (LOD) optimization. The limit is around 100'000 vertices for a scene, considering that the slowest currently used graphic cards cannot handle anything beyond that.</p>
- </li>
- <li>
- <p>Are any counts constantly increasing right before the game slows down or runs out of memory? Check whether you are accidentally adding objects in a loop, instead of only once.</p>
- </li>
- <li>
- <p>Verify that the numbers are plausible. If you think you generated a test scene out of “a few” boxes, but the StatsView shows ten thousands of triangles, then you probably have extra objects out of sight somewhere (due to barely visible materials, overlapping with other objects, scaled too big or too small to see, etc).</p>
- <div class="ulist">
- <ul>
- <li>
- <p>Example: In a test scene made up of boxes, you’d expect a vertex:triangle:object ratio of 8:12:1.</p>
- </li>
- <li>
- <p>Terrains, models and spheres have higher counts, depending on their size and <a href="level_of_detail.html" class="page">Level of Detail</a> (LOD). A high-poly model looks pretty in Blender, but you must find a lower-poly, low-LOD compromise if you want several large objects in one scene!</p>
- </li>
- </ul>
- </div>
- </li>
- <li>
- <p>If S (objects being switched) are high compared to F (objects used), then you use or generate too many different Materials (etc). You are unnecessarily forcing jME to re-load and re-bind objects (= Switches), which is bad for performance. Also if you have many transparent materials in your scene, this results in more switches, and you should use fewer transparent materials.</p>
- </li>
- <li>
- <p>If the M values (objects in memory) are high compared to F (objects used), that means a lot more GL objects are kept in memory than are actually used. This can happen in large scenes with many materials. Consider breaking the scene up and detaching objects while they are out of sight, so the built-in culling can optimize the scene.</p>
- </li>
- </ol>
- </div>
- <div class="paragraph">
- <p>What goal are you trying to achieve in general?</p>
- </div>
- <div class="olist arabic">
- <ol class="arabic">
- <li>
- <p>The values for (M) and (F) should be within the same order of magnitude. This means your code only loads objects that it actually needs, and that the hardware can actually handle.</p>
- </li>
- <li>
- <p>It’s okay if Switches (S) are lower than Used in Current Frame (F).</p>
- </li>
- <li>
- <p>The FPS should be 30 or more on the slowest hardware that you target.</p>
- </li>
- <li>
- <p>10'000-50'000 vertices is a typical average value for a scene.</p>
- </li>
- </ol>
- </div>
- <hr>
- <div class="paragraph">
- <p>See also:</p>
- </div>
- <div class="ulist">
- <ul>
- <li>
- <p><a href="https://hub.jmonkeyengine.org/t/good-triangles-count/22843">What’s a good triangle count?</a> Forum discussion</p>
- </li>
- <li>
- <p><a href="level_of_detail.html" class="page">Level of Detail</a></p>
- </li>
- </ul>
- </div>
- </div>
- </div>
- </article>
- <aside class="toc sidebar" data-title="Contents" data-levels="2">
- <div class="toc-menu"></div>
- </aside>
- </div>
- </main>
- </div>
- <footer class="footer">
- <p>Copyright 2020 jMonkeyEngine Wiki Contributors. Licensed BSD-3.</p>
- </footer>
- <script src="../../../_/js/vendor/docsearch.min.js"></script>
- <!-- fetched from https://cdn.jsdelivr.net/npm/docsearch.js@2/dist/cdn/docsearch.min.js -->
- <script>
- var search = docsearch({
- apiKey: 'a736b6d93de805e26ec2f49b55013fbd',
- indexName: 'jmonkeyengine',
- inputSelector: '#search-input',
- autocompleteOptions: { hint: false, keyboardShortcuts: ['s'] },
- algoliaOptions: { hitsPerPage: 10 }
- }).autocomplete
- search.on('autocomplete:closed', function () { search.autocomplete.setVal() })
- function focusSearchInput () { document.querySelector('#search-input').focus() }
- if (document.querySelector('.home-link.is-current')) window.addEventListener('load', focusSearchInput)
- </script>
- <script src="../../../_/js/site.js"></script>
- <script async src="../../../_/js/vendor/highlight.js"></script>
- </body>
- </html>
|