blob: ee9630c07117dfba6623d8d78a6306d37a31326b [file] [log] [blame]
<!-- HTML header for doxygen 1.8.6-->
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
<meta http-equiv="X-UA-Compatible" content="IE=9"/>
<meta name="generator" content="Doxygen 1.9.1"/>
<title>FlatBuffers: C++ Benchmarks</title>
<link href="tabs.css" rel="stylesheet" type="text/css"/>
<script type="text/javascript" src="jquery.js"></script>
<script type="text/javascript" src="dynsections.js"></script>
<link href="navtree.css" rel="stylesheet" type="text/css"/>
<script type="text/javascript" src="resize.js"></script>
<script type="text/javascript" src="navtreedata.js"></script>
<script type="text/javascript" src="navtree.js"></script>
<link href="search/search.css" rel="stylesheet" type="text/css"/>
<script type="text/javascript" src="search/searchdata.js"></script>
<script type="text/javascript" src="search/search.js"></script>
<link href="doxygen.css" rel="stylesheet" type="text/css" />
<link href="https://fonts.googleapis.com/css?family=Roboto:300,400,400italic,500,500italic,700,700italic|Roboto+Mono:400,700" rel="stylesheet">
<link href="style.css" rel="stylesheet" type="text/css"/>
</head>
<body>
<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
<div id="titlearea" style="height: 110px;">
<table cellspacing="0" cellpadding="0">
<tbody>
<tr style="height: 56px;">
<td id="commonprojectlogo">
<img alt="Logo" src="fpl_logo_small.png"/>
</td>
<td style="padding-left: 0.5em;">
<div id="projectname">FlatBuffers
</div>
<div style="font-size:12px;">
An open source project by <a href="https://developers.google.com/games/#Tools">FPL</a>.
</div>
</td>
</tr>
</tbody>
</table>
</div>
<!-- end header part -->
<!-- Generated by Doxygen 1.9.1 -->
<script type="text/javascript">
/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
var searchBox = new SearchBox("searchBox", "search",false,'Search','.html');
/* @license-end */
</script>
<script type="text/javascript" src="menudata.js"></script>
<script type="text/javascript" src="menu.js"></script>
<script type="text/javascript">
/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
$(function() {
initMenu('',true,false,'search.php','Search');
$(document).ready(function() { init_search(); });
});
/* @license-end */</script>
<div id="main-nav"></div>
</div><!-- top -->
<div id="side-nav" class="ui-resizable side-nav-resizable">
<div id="nav-tree">
<div id="nav-tree-contents">
<div id="nav-sync" class="sync"></div>
</div>
</div>
<div id="splitbar" style="-moz-user-select:none;"
class="ui-resizable-handle">
</div>
</div>
<script type="text/javascript">
/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
$(document).ready(function(){initNavTree('flatbuffers_benchmarks.html',''); initResizable(); });
/* @license-end */
</script>
<div id="doc-content">
<!-- window showing the filter options -->
<div id="MSearchSelectWindow"
onmouseover="return searchBox.OnSearchSelectShow()"
onmouseout="return searchBox.OnSearchSelectHide()"
onkeydown="return searchBox.OnSearchSelectKey(event)">
</div>
<!-- iframe showing the search results (closed by default) -->
<div id="MSearchResultsWindow">
<iframe src="javascript:void(0)" frameborder="0"
name="MSearchResults" id="MSearchResults">
</iframe>
</div>
<div class="PageDoc"><div class="header">
<div class="headertitle">
<div class="title">C++ Benchmarks </div> </div>
</div><!--header-->
<div class="contents">
<div class="textblock"><p><a class="anchor" id="md_Benchmarks"></a></p>
<p>Comparing against other serialization solutions, running on Windows 7 64bit. We use the LITE runtime for Protocol Buffers (less code / lower overhead), Rapid JSON (one of the fastest C++ JSON parsers around), and pugixml, also one of the fastest XML parsers.</p>
<p>We also compare against code that doesn't use a serialization library at all (the column "Raw structs"), which is what you get if you write hardcoded code that just writes structs. This is the fastest possible, but of course is not cross platform nor has any kind of forwards / backwards compatibility.</p>
<p>We compare against Flatbuffers with the binary wire format (as intended), and also with JSON as the wire format with the optional JSON parser (which, using a schema, parses JSON into a binary buffer that can then be accessed as before).</p>
<p>The benchmark object is a set of about 10 objects containing an array, 4 strings, and a large variety of int/float scalar values of all sizes, meant to be representative of game data, e.g. a scene format.</p>
<table class="markdownTable">
<tr class="markdownTableHead">
<th class="markdownTableHeadNone"></th><th class="markdownTableHeadNone">FlatBuffers (binary) </th><th class="markdownTableHeadNone">Protocol Buffers LITE </th><th class="markdownTableHeadNone">Rapid JSON </th><th class="markdownTableHeadNone">FlatBuffers (JSON) </th><th class="markdownTableHeadNone">pugixml </th><th class="markdownTableHeadNone">Raw structs </th></tr>
<tr class="markdownTableRowOdd">
<td class="markdownTableBodyNone">Decode + Traverse + Dealloc (1 million times, seconds) </td><td class="markdownTableBodyNone">0.08 </td><td class="markdownTableBodyNone">302 </td><td class="markdownTableBodyNone">583 </td><td class="markdownTableBodyNone">105 </td><td class="markdownTableBodyNone">196 </td><td class="markdownTableBodyNone">0.02 </td></tr>
<tr class="markdownTableRowEven">
<td class="markdownTableBodyNone">Decode / Traverse / Dealloc (breakdown) </td><td class="markdownTableBodyNone">0 / 0.08 / 0 </td><td class="markdownTableBodyNone">220 / 0.15 / 81 </td><td class="markdownTableBodyNone">294 / 0.9 / 287 </td><td class="markdownTableBodyNone">70 / 0.08 / 35 </td><td class="markdownTableBodyNone">41 / 3.9 / 150 </td><td class="markdownTableBodyNone">0 / 0.02 / 0 </td></tr>
<tr class="markdownTableRowOdd">
<td class="markdownTableBodyNone">Encode (1 million times, seconds) </td><td class="markdownTableBodyNone">3.2 </td><td class="markdownTableBodyNone">185 </td><td class="markdownTableBodyNone">650 </td><td class="markdownTableBodyNone">169 </td><td class="markdownTableBodyNone">273 </td><td class="markdownTableBodyNone">0.15 </td></tr>
<tr class="markdownTableRowEven">
<td class="markdownTableBodyNone">Wire format size (normal / zlib, bytes) </td><td class="markdownTableBodyNone">344 / 220 </td><td class="markdownTableBodyNone">228 / 174 </td><td class="markdownTableBodyNone">1475 / 322 </td><td class="markdownTableBodyNone">1029 / 298 </td><td class="markdownTableBodyNone">1137 / 341 </td><td class="markdownTableBodyNone">312 / 187 </td></tr>
<tr class="markdownTableRowOdd">
<td class="markdownTableBodyNone">Memory needed to store decoded wire (bytes / blocks) </td><td class="markdownTableBodyNone">0 / 0 </td><td class="markdownTableBodyNone">760 / 20 </td><td class="markdownTableBodyNone">65689 / 4 </td><td class="markdownTableBodyNone">328 / 1 </td><td class="markdownTableBodyNone">34194 / 3 </td><td class="markdownTableBodyNone">0 / 0 </td></tr>
<tr class="markdownTableRowEven">
<td class="markdownTableBodyNone">Transient memory allocated during decode (KB) </td><td class="markdownTableBodyNone">0 </td><td class="markdownTableBodyNone">1 </td><td class="markdownTableBodyNone">131 </td><td class="markdownTableBodyNone">4 </td><td class="markdownTableBodyNone">34 </td><td class="markdownTableBodyNone">0 </td></tr>
<tr class="markdownTableRowOdd">
<td class="markdownTableBodyNone">Generated source code size (KB) </td><td class="markdownTableBodyNone">4 </td><td class="markdownTableBodyNone">61 </td><td class="markdownTableBodyNone">0 </td><td class="markdownTableBodyNone">4 </td><td class="markdownTableBodyNone">0 </td><td class="markdownTableBodyNone">0 </td></tr>
<tr class="markdownTableRowEven">
<td class="markdownTableBodyNone">Field access in handwritten traversal code </td><td class="markdownTableBodyNone">typed accessors </td><td class="markdownTableBodyNone">typed accessors </td><td class="markdownTableBodyNone">manual error checking </td><td class="markdownTableBodyNone">typed accessors </td><td class="markdownTableBodyNone">manual error checking </td><td class="markdownTableBodyNone">typed but no safety </td></tr>
<tr class="markdownTableRowOdd">
<td class="markdownTableBodyNone">Library source code (KB) </td><td class="markdownTableBodyNone">15 </td><td class="markdownTableBodyNone">some subset of 3800 </td><td class="markdownTableBodyNone">87 </td><td class="markdownTableBodyNone">43 </td><td class="markdownTableBodyNone">327 </td><td class="markdownTableBodyNone">0 </td></tr>
</table>
<h2><a class="anchor" id="autotoc_md143"></a>
Some other serialization systems we compared against but did not benchmark (yet), in rough order of applicability:</h2>
<ul>
<li>Cap'n'Proto promises to reduce Protocol Buffers much like FlatBuffers does, though with a more complicated binary encoding and less flexibility (no optional fields to allow deprecating fields or serializing with missing fields for which defaults exist). It currently also isn't fully cross-platform portable (lack of VS support).</li>
<li>msgpack: has very minimal forwards/backwards compatibility support when used with the typed C++ interface. Also lacks VS2010 support.</li>
<li>Thrift: very similar to Protocol Buffers, but appears to be less efficient, and have more dependencies.</li>
<li>YAML: a superset of JSON and otherwise very similar. Used by e.g. Unity.</li>
<li>C# comes with built-in serialization functionality, as used by Unity also. Being tied to the language, and having no automatic versioning support limits its applicability.</li>
<li>Project Anarchy (the free mobile engine by Havok) comes with a serialization system, that however does no automatic versioning (have to code around new fields manually), is very much tied to the rest of the engine, and works without a schema to generate code (tied to your C++ class definition).</li>
</ul>
<h2><a class="anchor" id="autotoc_md144"></a>
Code for benchmarks</h2>
<p>Code for these benchmarks sits in <code>benchmarks/</code> in git branch <code>benchmarks</code>. It sits in its own branch because it has submodule dependencies that the main project doesn't need, and the code standards do not meet those of the main project. Please read <code>benchmarks/cpp/README.txt</code> before working with the code.</p>
<p><br />
</p>
</div></div><!-- contents -->
</div><!-- PageDoc -->
</div><!-- doc-content -->
<!-- Google Analytics -->
<script>
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
})(window,document,'script','//www.google-analytics.com/analytics.js','ga');
ga('create', 'UA-49880327-7', 'auto');
ga('send', 'pageview');
</script>
</body>
</html>