Synopse Open Source - Tag - DBXJSONmORMot MVC / SOA / ORM and friends2024-02-02T17:08:25+00:00urn:md5:cc547126eb580a9adbec2349d7c65274DotclearBenchmarking JsonDataObjects JSON parserurn:md5:a7e885e4f4f537240b0b8987bacf97862015-02-16T10:30:00+01:002015-02-16T12:34:51+01:00AB4327-GANDIOpen SourceblogCrossPlatformDBXJSONDelphidwsJSONJSONJsonDataObjectsORMperformanceQDACsuperobjectUnicode<p>There is a <a href="http://andy.jgknet.de/blog/2015/02/json-parser-jsondataobjects-is-now-on-github/">
new player in town</a>.<br />
Since it has been written by Andreas Hausladen, the maintainer of the
<a href="http://andy.jgknet.de/blog/ide-tools/">great Delphi IDE fix packs</a>,
this new JSON library is very promising.</p>
<p><img src="http://www.meanstack.ninja/wp-content/uploads/2015/01/json-logo.png" alt="" width="345" height="165/" /></p>
<p>And in fact, it is fast, and sounds pretty great!<br />
Here are some numbers, compared with <em>SuperObject</em>, standard
<em>DBXJson</em>, <em>dwsJSON, QDAC</em> and <em>mORMot</em>.<br />
Please refer to <a href="https://blog.synopse.info?post/post/json-benchmark-delphi-mormot-superobject-dwsjson-dbxjson">previous
benchmark articles</a> about those libraries. We will now focus on
<em>JsonDataObjects</em>.</p> <pre>
JSON benchmarking
-------------------
1. Small content
1.1. Synopse record:
- Read: 50,000 assertions passed 153.07ms 326,641/s
- Access: 100,000 assertions passed 958us 52,192,066/s
- Write: 50,000 assertions passed 105.84ms 472,411/s
Total failed: 0 / 200,000 - Synopse record PASSED 260.33ms
1.2. Synopse variant:
- Read: 50,000 assertions passed 381.95ms 130,904/s
- Access direct: 100,000 assertions passed 67.59ms 739,677/s
- Access late binding: 100,000 assertions passed 699.14ms 71,516/s
- Write: 50,000 assertions passed 215.65ms 231,857/s
Total failed: 0 / 300,000 - Synopse variant PASSED 1.36s
1.3. Synopse cross platform variant:
- Read: 50,000 assertions passed 645.38ms 77,473/s
- Access direct: 100,000 assertions passed 41.87ms 1,194,086/s
- Access late binding: 100,000 assertions passed 612.42ms 81,643/s
- Write: 50,000 assertions passed 625.52ms 79,932/s
Total failed: 0 / 300,000 - Synopse cross platform variant PASSED 1.92s
1.4. Super object record:
- Read: 50,000 assertions passed 2.37s 21,014/s
- Access: 100,000 assertions passed 1.01ms 49,504,950/s
- Write: 50,000 assertions passed 1.80s 27,651/s
Total failed: 0 / 200,000 - Super object record PASSED 4.19s
1.5. Super object properties:
- Read: 50,000 assertions passed 895.68ms 55,823/s
- Access: 100,000 assertions passed 369.84ms 135,192/s
- Write: 50,000 assertions passed 370.30ms 135,025/s
Total failed: 0 / 200,000 - Super object properties PASSED 1.63s
1.6. dws JSON:
- Read: 50,000 assertions passed 273.69ms 182,683/s
- Access: 100,000 assertions passed 87.51ms 571,356/s
- Write: 50,000 assertions passed 204.84ms 244,089/s
Total failed: 0 / 200,000 - dws JSON PASSED 569.01ms
1.7. DBXJSON:
- Read: 50,000 assertions passed 4.83s 10,340/s
- Access: 100,000 assertions passed 49.40ms 1,012,043/s
- Write: 50,000 assertions passed 616.26ms 81,133/s
Total failed: 0 / 200,000 - DBXJSON PASSED 5.50s
1.8. QDAC:
- Read: 50,000 assertions passed 639.13ms 78,230/s
- Access: 100,000 assertions passed 95.95ms 521,061/s
- Write: 50,000 assertions passed 386.40ms 129,398/s
Total failed: 0 / 200,000 - QDAC PASSED 1.12s
<strong> 1.9. Json data objects:
- Read: 50,000 assertions passed 248.87ms 200,900/s
- Access: 100,000 assertions passed 7.54ms 6,629,541/s
- Write: 50,000 assertions passed 109.55ms 456,379/s
Total failed: 0 / 200,000 - Json data objects PASSED 368.36ms
</strong>
2. Big content
2.1. Depth content:
- Download files if necessary: no assertion 408us
- Synopse read variant: 1 assertion passed 167.89ms 297,799/s 227 KB
- Synopse read to BSON: 2 assertions passed 2.87ms 17,379,214/s 159 KB
- Synopse cross platform: 1 assertion passed 3.94ms 12,690,355/s 300 KB
<strong>! - Super object read: 1 / 1 FAILED 17.67ms 2,828,374/s</strong>
- dws JSON read: 1 assertion passed 4.83ms 10,349,824/s 1.5 MB
- DBXJSON read: 1 assertion passed 92.25ms 541,958/s 1.9 MB
- Json data objects read: 1 assertion passed 2.73ms 18,254,837/s 1.5 MB
Total failed: 1 / 8 - Depth content FAILED 304.11ms
2.2. Table content:
- Download files if necessary: no assertion 469us 17,543,710/s
- Synopse parse: 1 assertion passed 2.70ms 3,043,655/s 1.2 MB
- Synopse ORM loop: 41,135 assertions passed 6.67ms 1,233,433/s 1.2 MB
- Synopse ORM list: 41,135 assertions passed 6.94ms 1,184,422/s 1016 KB
- Synopse table direct: 41,135 assertions passed 19.38ms 424,509/s 1.2 MB
- Synopse table variant: 41,135 assertions passed 97.61ms 84,283/s 1.2 MB
- Synopse doc variant: 41,137 assertions passed 31.50ms 261,141/s 3.0 MB
- Synopse late binding: 41,137 assertions passed 106.78ms 77,045/s 3.0 MB
- Synopse cross ORM: 41,135 assertions passed 18.99ms 433,228/s 1.9 MB
- Synopse cross direct: 41,135 assertions passed 20.19ms 407,418/s 1.9 MB
- Synopse cross variant: 41,135 assertions passed 100.13ms 82,162/s 1.9 MB
- Synopse to BSON: 2 assertions passed 10.57ms 777,893/s 1.0 MB
- Super object properties: 41,136 assertions passed 180.95ms 45,463/s 6.3 M
B
- Super object record: 41,136 assertions passed 150.22ms 54,763/s 6.3 MB
- dws JSON: 41,136 assertions passed 29.29ms 280,871/s 4.7 MB
- DBXJSON: 41,136 assertions passed 265.78ms 30,953/s 9.10 MB
<strong>- JsonDataObjects: 41,136 assertions passed 15.41ms 533,770/s 2.6 MB</strong>
- QDAC: 41,136 assertions passed 41.53ms 198,073/s 5.9 MB
Total failed: 0 / 617,038 - Table content PASSED 1.13s
2.3. Huge content:
- Download files if necessary: no assertion 447us
- Synopse beautifier: 1 assertion passed 1.58s 31,558/s 104 B
- Synopse read record: 4 assertions passed 1.44s 143,250/s 113.5 MB
- Synopse read variant: 2 assertions passed 3.38s 61,027/s 377.4 MB
- Synopse cross platform: 2 assertions passed 5.46s 37,824/s 424.8 MB
- Synopse read to BSON: 3 assertions passed 1.96s 105,013/s 168.1 MB
- Super object read: 2 assertions passed 8.99s 22,951/s 1.1 GB
- dws JSON read: 2 assertions passed 3.20s 64,466/s 672.7 MB
- DBXJSON read: no assertion 151us 331,125,827/s
DBXJSON will raise EOutOfMemory for 185 MB JSON in Win32 -> skip
<strong>- Json data objects read: 2 assertions passed 1.70s 121,237/s 329.6 MB
- Json data objects beautifier: no assertion 7.59s 6,585/s 510.6 MB</strong>
- QDAC read: 2 assertions passed 8.41s 24,558/s 1.1 GB
</pre>
<pre>
Total failed: 0 / 20 - Huge content PASSED 36.90s
Generated with: Delphi XE7 compiler
Time elapsed for all tests: 55.30s
Tests performed at 16/02/2015 09:41:34
Total assertions failed for all test suits: 1 / 2,617,066
! Some tests FAILED: please correct the code.
</pre>
<p>As you can see, the latest revision of <em>SuperObject</em>, retrieved
from SVN, failed to pass a test.<br />
There is a weird depth restriction in this library.<br />
Since we don't use this library, which is slow and just blowing under Win64, it
is not a problem for us.</p>
<p>We did not include <em>XSuperObject</em> here, since <a href="https://blog.synopse.info?post/post/json-benchmark-delphi-mormot-superobject-dwsjson-dbxjson">we already
benchmarked it</a>: it is even slower than <em>SuperObject</em>.</p>
<p>As you can see, <em>JsonDataObjects</em> is a great library, fastest
that any other implementations, when using the general purpose
DOM/node-oriented use case.<br />
As always, our ORM-optimized version is fastest for table reading
(see <span style="font-family: 'Courier New', Courier, monospace; font-size: 1.1em;">Synopse ORM
loop</span> and <span style="font-family: 'Courier New', Courier, monospace; font-size: 1.1em;">Synopse ORM
list</span>), but it is not 100% fair since it has been optimized for a single
use case - which is the main bottleneck of any JSON-based ORM like
<em>mORMot</em>.<br />
Take a look at our <span style="font-family: 'Courier New', Courier, monospace; font-size: 1.1em;">Synopse
parse</span>: it is in fact our <a href="https://blog.synopse.info?post/post/2011/06/02/Fast-JSON-parsing">SAX-like JSON parser</a>, which is able to
read, parse, unescape and fill a list of pointers with each data in more than
3,000,000 rows per seconds, with almost no memory use. A DOM/node approach can
only reach 500,000 rows per second, for <em>JsonDataObjects</em>.<br />
All those numbers are always high: in practice, keeping away from the RTL
<em>DBXJson.pas</em>, or <em>SuperObject</em> units is enough.</p>
<p>In a multi-threaded environment, there may be some bottlenecks of
<em>JsonDataObjects</em> writing, which uses temporary strings for building the
JSON text from number values, so relies heavily on the memory manager (more
than <em>dwsJSON</em> or <em>mORMot</em> implementations).<br />
You can see this behavior when comparing the <span style="font-family: 'Courier New', Courier, monospace; font-size: 1.1em;">Json data
objects beautifier</span> time and memory consumption with our
SAX-based <span style="font-family: 'Courier New', Courier, monospace; font-size: 1.1em;">Synopse
beautifier</span> (which, BTW preserve the original floating point
precision).</p>
<p>IMHO the only missing feature is a "path query", i.e. allow to retrieve
values by a path.<br />
It could be nice to be able to write (as with other libraries):</p>
<pre>
Check(doc.A['glossary.GlossDiv.GlossList.GlossEntry.GlossDef.GlossSeeAlso'].S[0]='GML');
</pre>
<div>instead of</div>
<div>
<pre>
Check(doc.O['glossary'].O['GlossDiv'].O['GlossList'].<br /> O['GlossEntry'].O['GlossDef'].A['GlossSeeAlso'].S[0]='GML');
</pre></div>
<p>Congrats Andreas for your great work!</p>
<p>Source code of the test is available in <a href="https://github.com/synopse/mORMot/blob/master/SQLite3/Samples/25%20-%20JSON%20performance/JSONPerfTestCases.pas">
our source code repository</a>.<br />
And feedback is <a href="http://synopse.info/forum/viewtopic.php?id=2362">welcome on our forum</a>, as
usual.</p>Benchmarking QDAC3 JSON parserurn:md5:b91a5f3373be4b2bd357c53d898ec15c2015-02-01T14:15:00+01:002020-07-03T09:29:59+02:00AB4327-GANDImORMot FrameworkblogCrossPlatformDBXJSONDelphidwsJSONJSONORMperformanceQDACUnicode<p>Do you know QDAC3 ?<br />
This is an open source project, from China (with Chinese comments and exception
errors messages, but the methods and variables are in English).<br />
It is cross-platform, and told to be very fast about JSON process.</p>
<p><img src="http://blog.qdac.cc/wp-content/uploads/2014/08/QQ%E6%88%AA%E5%9B%BE20140825084430-300x213.jpg" alt="" /></p>
<p>You can download this Open Source project code from <a href="http://sourceforge.net/projects/qdac3">http://sourceforge.net/projects/qdac3</a><br />
And their blog - in Chinese - is at <a href="http://blog.qdac.cc/">http://blog.qdac.cc/</a></p>
<p>So I <a href="http://synopse.info/fossil/info/e758ebb6c0">included QDAC3 in
our "<em>25 - JSON performance</em>" sample</a>.<br />
Numbers are talking, now.</p> <p>Here are some numbers, compiled with XE7 under Win32:</p>
<pre>
JSON benchmarking<br /> -------------------<br />1. Small content<br /> 1.1. Synopse record:<br /> - Read: 50,000 assertions passed 158.31ms 315,822/s<br /> - Access: 100,000 assertions passed 795us 62,893,081/s<br /> - Write: 50,000 assertions passed 111.58ms 448,088/s<br /> Total failed: 0 / 200,000 - Synopse record PASSED 271.46ms<br /> 1.2. Synopse variant:<br /> - Read: 50,000 assertions passed 364.70ms 137,096/s<br /> - Access direct: 100,000 assertions passed 61.71ms 810,149/s<br /> - Access late binding: 100,000 assertions passed 722.41ms 69,212/s<br /> - Write: 50,000 assertions passed 218.17ms 229,174/s<br /> Total failed: 0 / 300,000 - Synopse variant PASSED 1.36s<br /> 1.3. Synopse cross platform variant:<br /> - Read: 50,000 assertions passed 642.89ms 77,773/s<br /> - Access direct: 100,000 assertions passed 38.80ms 1,288,560/s<br /> - Access late binding: 100,000 assertions passed 627.81ms 79,641/s<br /> - Write: 50,000 assertions passed 607.77ms 82,267/s<br /> Total failed: 0 / 300,000 - Synopse cross platform variant PASSED 1.91s<br /> <strong>1.4. QDAC:<br /> - Read: 50,000 assertions passed 637.91ms 78,379/s<br /> - Access: 100,000 assertions passed 89.47ms 558,846/s<br /> - Write: 50,000 assertions passed 391.53ms 127,703/s</strong><br /> Total failed: 0 / 200,000 - QDAC PASSED 1.12s<br /><br />2. Big content<br /> 2.1. Depth content:<br /> - Download files if necessary: no assertion 358us<br /> - Synopse read variant: 1 assertion passed 161.44ms 309,712/s 227 KB<br /> - Synopse read to BSON: 2 assertions passed 2.62ms 19,025,875/s 159 KB<br /> - Synopse cross platform: 1 assertion passed 3.85ms 12,960,082/s 300 KB<br /> Total failed: 0 / 4 - Depth content PASSED 174.67ms<br /> 2.2. Table content:<br /> - Download files if necessary: no assertion 587us 14,017,035/s<br /> - Synopse parse: 1 assertion passed 2.67ms 3,077,815/s 1.2 MB<br /> - Synopse ORM loop: 41,135 assertions passed 6.25ms 1,316,320/s 1.2 MB<br /> - Synopse ORM list: 41,135 assertions passed 6.77ms 1,214,138/s 1016 KB<br /> - Synopse table direct: 41,135 assertions passed 19.66ms 418,463/s 1.2 MB<br /> - Synopse table variant: 41,135 assertions passed 99.07ms 83,037/s 1.2 MB<br /> - Synopse doc variant: 41,137 assertions passed 31.13ms 264,227/s 3.0 MB<br /> - Synopse late binding: 41,137 assertions passed 107.81ms 76,305/s 3.0 MB<br /> - Synopse cross ORM: 41,135 assertions passed 17.14ms 479,876/s 1.9 MB<br /> - Synopse cross direct: 41,135 assertions passed 19.59ms 419,937/s 1.9 MB<br /> - Synopse cross variant: 41,135 assertions passed 102.76ms 80,053/s 1.9 MB<br /> - Synopse to BSON: 2 assertions passed 10.64ms 772,923/s 1.0 MB<br /> - <strong>QDAC: 41,136 assertions passed 41.42ms 198,604/s 5.9 MB</strong><br /> Total failed: 0 / 411,358 - Table content PASSED 491.91ms<br /> 2.3. Huge content:<br /> - Download files if necessary: no assertion 499us<br /> - Synopse beautifier: 1 assertion passed 1.36s 36,554/s 395.5 MB<br /> - Synopse read record: 4 assertions passed 1.42s 144,924/s 113.5 MB<br /> - Synopse read variant: 2 assertions passed 3.25s 63,404/s 377.4 MB<br /> - Synopse cross platform: 2 assertions passed 5.35s 38,558/s 424.9 MB<br /> - Synopse read to BSON: 3 assertions passed 1.95s 105,727/s 168.1 MB<br /> - <strong>QDAC read: 2 assertions passed 8.28s 24,920/s 1.1 GB</strong><br /> Total failed: 0 / 14 - Huge content PASSED 22.73s<br /><br />Generated with: Delphi XE7 compiler<br />Time elapsed for all tests: 28.08s<br />Tests performed at 01/02/2015 13:46:04<br />Total assertions failed for all test suits: 0 / 1,411,376<br /> All tests passed successfully.
</pre>
<p>For small objects, it performs very well - but of course slower than mORMot
code.<br />
But for bigger content, it consumes a lot of memory.</p>
<p>For instance, when reading a table of data results as JSON array of
objects:</p>
<ul>
<li>Our ORM code performs at 1,316,320 rows/s and uses 1.2 MB of RAM;</li>
<li>QDAC achieves 198,604 row/s and uses 5.9 MB.</li>
</ul>
<p>That is 8 times slower, and using 5 times more memory.</p>
<p>Performance is similar under Win64:</p>
<ul>
<li>Our ORM code performs at 1,190,076 rows/s and uses 1.3 MB of RAM;</li>
<li>QDAC achieves 178,607 row/s and uses 9.3 MB.</li>
</ul>
<p>That is 8 times slower, and using 7 times more memory.</p>
<p>We did not test QDAC cross-platform abilities, nor its RTTI methods, which
should be even slower.</p>
<p>But we found a very annoying implementation issue of the JSON
standard.<br />
We discovered that QDAC it is not able to parse "" as a key, whereas it is
valid JSON key.<br />
All other parsers do accept this sample.json reference content.<br />
I hope they will fix this issue.</p>
<p>Comments and feedback is <a href="http://synopse.info/forum/viewtopic.php?id=2330">welcome on our forum</a>, as
usual.</p>New sample for JSON performance: mORMot vs SuperObject/XSuperObject/dwsJSON/DBXJSONurn:md5:d7475fcfa6e4216fc328ea55e1ad9a312014-05-18T16:05:00+02:002020-07-03T09:29:59+02:00AB4327-GANDImORMot FrameworkblogDBXJSONDelphiDTOdwsJSONGoodPracticeJSONLateBindingmORMotnativeobjectORMperformancerecordSourcesuperobjectTObjectList<p>We have just added a new "<a href="http://synopse.info/fossil/finfo?name=SQLite3/Samples/25+-+JSON+performance/JSONPerfTestCases.pas">25
- JSON performance</a>" sample to benchmark JSON process, using well most known
Delphi libraries...</p>
<blockquote>
<p><strong>A new fight<br />
featuring<br />
mORMot vs <a href="https://code.google.com/p/superobject/">SuperObject</a>/<a href="https://code.google.com/p/x-superobject/">XSuperObject</a>/<a href="https://code.google.com/p/dwscript/source/browse/trunk/Source/dwsJSON.pas">dwsJSON</a>/<a href="http://docwiki.embarcadero.com/Libraries/XE5/en/Data.DBXJSON">DBXJSON</a></strong></p>
</blockquote>
<p>On <em>mORMot</em> side, it covers <code>TDocVariant</code>, late binding,
<code>TSQLTable</code>, ORM, record access, BSON...</p>
<p><img src="http://i.i.cbsi.com/cnwk.1d/i/tim/2011/02/02/groundhog_adp.jpg" alt="" width="292" height="198/" /></p>
<p>We tried to face several scenarios:</p>
<ul>
<li>parse/access/write iteration over a small JSON document,</li>
<li>read of deeply nested 680 KB JSON (here mORMot is slower than
SO/dwsJSON),</li>
<li>read of one 180 MB JSON file (with on-the-fly adaptation to fit a record
layout),</li>
<li>named access to all rows and columns of a 1 MB JSON table, extracted from a
SQL request (with comparison with our ORM performance).</li>
</ul>
<p>On average and in details, <em>mORMot</em> is the fastest in almost all
scenarios (with an amazing performance for table/ORM processing),
<em>dwsJSON</em> performs very well (better than SuperObject), and
<em>DBXJSON</em> is the slowest (by far, but XE6 version is faster than
XE4).</p> Here are some values, compiled with XE6 on my Core i7 notebook.
<p>You have the number of iterations per second, and the peak memory used
during each process.</p>
<blockquote>
<p> <strong> JSON benchmarking<br />
-------------------<br />
<br />
1. Small content<br />
<br />
1.1. Synopse record:</strong><br />
- Read: 25,000 assertions passed 70.67ms 353,721/s<br />
- Access: 50,000 assertions passed 493us 50,709,939/s<br />
- Write: 25,000 assertions passed 49.25ms 507,562/s<br />
Total failed: 0 / 100,000 - Synopse record PASSED
121.03ms<br />
<br />
<strong>1.2. Synopse variant:</strong><br />
- Read: 25,000 assertions passed 120.29ms 207,827/s<br />
- Access direct: 50,000 assertions passed 29.04ms
860,614/s<br />
- Access late binding: 50,000 assertions passed 98.13ms
254,764/s<br />
- Write: 25,000 assertions passed 57.84ms 432,204/s<br />
Total failed: 0 / 150,000 - Synopse variant PASSED
306.04ms<br />
<br />
<strong>1.3. Super object record:</strong><br />
- Read: 25,000 assertions passed 2.00s 12,470/s<br />
- Access: 50,000 assertions passed 408us 61,274,509/s<br />
- Write: 25,000 assertions passed 1.71s 14,539/s<br />
Total failed: 0 / 100,000 - Super object record PASSED
3.72s<br />
<br />
<strong> 1.4. Super object properties:</strong><br />
- Read: 25,000 assertions passed 2.14s 11,631/s<br />
- Access: 50,000 assertions passed 1.92s 12,971/s<br />
- Write: 25,000 assertions passed 186.63ms 133,952/s<br />
Total failed: 0 / 100,000 - Super object properties PASSED
4.26s<br />
<br />
<strong>1.5. dws JSON:</strong><br />
- Read: 25,000 assertions passed 136.42ms 183,250/s<br />
- Access: 50,000 assertions passed 37.07ms 674,236/s<br />
- Write: 25,000 assertions passed 97.86ms 255,464/s<br />
Total failed: 0 / 100,000 - dws JSON PASSED 273.66ms<br />
<br />
<strong> 1.6. DBXJSON:</strong><br />
- Read: 25,000 assertions passed 2.35s 10,622/s<br />
- Access: 50,000 assertions passed 23.38ms 1,069,244/s<br />
- Write: 25,000 assertions passed 309.64ms 80,737/s<br />
Total failed: 0 / 100,000 - DBXJSON PASSED 2.68s<br />
<br />
<strong>2. Big content<br />
<br />
2.1. Depth content:</strong><br />
- Download files if necessary: no assertion 384us<br />
- Synopse read variant: 1 assertion passed 87.99ms 284,100/s
337 KB<br />
- Synopse read to BSON: 2 assertions passed 2.55ms
9,784,735/s 155 KB<br />
- Super object read: 2 assertions passed 9.20ms 2,716,210/s
529 KB<br />
- dws JSON read: 1 assertion passed 5.55ms 4,503,693/s
439 KB<br />
- DBXJSON read: 1 assertion passed 92.20ms 271,126/s
679 KB<br />
Total failed: 0 / 7 - Depth content PASSED 202.86ms<br />
<br />
<strong>2.2. Table content:</strong><br />
- Download files if necessary: no assertion 356us
23,112,359/s<br />
- Synopse parse: 1 assertion passed 2.69ms 3,052,690/s
1.2 MB<br />
- Synopse ORM loop: 41,135 assertions passed 6.14ms
1,339,465/s 1.2 MB<br />
- Synopse ORM list: 41,135 assertions passed 6.52ms
1,260,070/s 951 KB<br />
- Synopse table direct: 41,135 assertions passed 20.40ms
403,126/s 1.2 MB<br />
- Synopse table variant: 41,135 assertions passed 20.29ms
405,330/s 1.2 MB<br />
- Synopse doc variant: 41,137 assertions passed 39.80ms
206,661/s 4.6 MB<br />
- Synopse late binding: 41,137 assertions passed 34.45ms
238,768/s 4.6 MB<br />
- Synopse to BSON: 2 assertions passed 8.92ms 922,206/s
1.1 MB<br />
- Super object properties: 41,136 assertions passed 2.14s
3,840/s 6.3 MB<br />
- Super object record: 41,136 assertions passed 148.57ms
55,373/s 6.3 MB<br />
- dws JSON: 41,136 assertions passed 28.87ms 284,888/s
4.7 MB<br />
- DBXJSON: 1 assertion passed 236.75ms 34,749/s 9.9
MB<br />
Total failed: 0 / 370,226 - Table content PASSED 2.70s<br />
<br />
<strong> 2.3. Huge content:</strong><br />
- Download files if necessary: no assertion 428us<br />
- Synopse read record: 4 assertions passed 1.52s 135,810/s
122.6 MB<br />
- Synopse read variant: 2 assertions passed 2.45s 84,134/s
512.9 MB<br />
- Synopse read to BSON: 3 assertions passed 2.01s 102,333/s
168.1 MB<br />
- Super object read: 2 assertions passed 9.07s 22,769/s
1.1 GB<br />
- dws JSON read: 2 assertions passed 3.26s 63,323/s
672.7 MB<br />
- DBXJSON read: no assertion 703us 35,561,877/s<br />
DBXJSON will raise EOutOfMemory for 185 MB JSON in Win32
-> skip<br />
Total failed: 0 / 13 - Huge content PASSED 18.92s<br />
<br />
Generated with: Delphi XE6 compiler<br />
Time elapsed for all tests: 33.22s<br />
<br />
Tests performed at 17/05/2014 08:47:02<br />
Total assertions failed for all test suits: 0 / 1,020,246<br />
! All tests passed successfully.</p>
</blockquote>
<p><em>SuperObject</em> has some issues for property names lookup...</p>
<p>I've written a <code>TTestTableContent.SuperObjectRecord</code> dedicated
method: accessing the values via a record (and RTTI) is much faster than using
<code>S[...] I[...]</code> and such methods.<br />
Current version did not support XE6 compiler (I had to write some
<code>$ifdef</code> by hand), and when compiled for Win64, the sample program
just exploded... <em>SuperObject</em> needs some tuning!</p>
<p>It is worth saying that <em>dwsJSON</em> performs very well, for its
purpose.<br />
What is written <a href="http://www.delphitools.info/2012/09/17/spotlight-on-dwsjson/">in this blog
article</a> is perfectly true, in comparison to <em>SuperObject</em> or
<em>DBXJSON</em>.<br />
Even on Win64 platform.<br />
Great work, Eric!</p>
<p><em>DBXJSON</em> is pretty slow, and is even giving an
<code>EOutOfMEmory</code> error in Win32 for the huge content (more than 2GB is
used!) - under Win64, it passes, with 3GB used for the 180 MB JSON file.<br />
In the meanwhile, mORMot uses 150 MB of memory with records. :)</p>
<p>Here are some number concerning <em>XSuperObject</em>:</p>
<blockquote>
<p><strong> 1.3. X super object record:</strong><br />
- Read: 25,000 assertions passed 12.68s 1,971/s<br />
- Access: 50,000 assertions passed 517us 48,355,899/s<br />
- Write: 25,000 assertions passed 2.32s 10,737/s<br />
Total failed: 0 / 100,000 - X super object record PASSED
15.01s<br />
<br />
<strong> 1.4. X super object properties:</strong><br />
- Read: 25,000 assertions passed 10.14s 2,463/s<br />
- Access: 50,000 assertions passed 307.49ms 81,302/s<br />
- Write: 25,000 assertions passed 435.44ms 57,412/s<br />
Total failed: 0 / 100,000 - X super object properties PASSED
10.89s</p>
</blockquote>
<p>I was not able to run <em>SuperObject</em> and <em>XSuperObject</em> in the
same application at once... so you have to use compiler defines in the sample
source code, to let one of the two libraries be compiled.<br />
But <em>XSuperObject</em> is not optimized for speed, it is in fact very slow,
even slower than <em>SuperObject</em> - and not in the race when compared to
<em>dwsJSON</em> or <em>mORMot</em>.</p>
<p>The <em>mORMot</em> code has some advantages, especially for ORM / table
process.<br />
The ability to use <code>record</code> and <em>dynamic arrays</em> to store the
content make it very convenient, and also powerful (see how we used enhanced
RTTI for serialization, but a custom sub-record type for a "polygon /
multi-polygon coordinates" structure which wouldn't be able to be accessed via
regular records from JSON. Our record-based RTTI gives also impressive
results, in both terms of speed and memory consumption.<br />
And late-binding for properties access gives very readable code.</p>
<p>To conclude, which syntax do you prefer?</p>
<pre>
<code>// Synopse direct record access
Check(gloss.glossary.GlossDiv.GlossList.GlossEntry.GlossDef.GlossSeeAlso[0]='GML');
// Synopse TDocVariant with properties
Check(DocVariantData(doc.GetValueByPath([
'glossary','GlossDiv','GlossList','GlossEntry','GlossDef','GlossSeeAlso'])).Value[0]='GML');
// Synopse TDocVariant with late binding
Check(doc.glossary.GlossDiv.GlossList.GlossEntry.GlossDef.GlossSeeAlso._(0)='GML');
// SuperObject properties
check(obj['glossary.GlossDiv.GlossList.GlossEntry.GlossDef.GlossSeeAlso[0]'].AsString='GML');
// SuperObject direct record access
Check(gloss.glossary.GlossDiv.GlossList.GlossEntry.GlossDef.GlossSeeAlso[0]='GML');
// XSuperObject
check(obj['glossary.GlossDiv.GlossList.GlossEntry.GlossDef.GlossSeeAlso[0]'].AsString='GML');
// dwsJSON
check(obj['glossary']['GlossDiv']['GlossList']['GlossEntry']['GlossDef']['GlossSeeAlso'][0].AsString='GML');
// DBXJSON
check(((((((obj.GetValue('glossary') as TJSONObject).
GetValue('GlossDiv') as TJSONObject).
GetValue('GlossList') as TJSONObject).
GetValue('GlossEntry') as TJSONObject).
GetValue('GlossDef') as TJSONObject).
GetValue('GlossSeeAlso') as TJSONArray).Get(0).Value='GML');
</code>
</pre>
Any feedback is welcome, including your own benchmark results, <a href="http://synopse.info/forum/viewtopic.php?id=1764">in our forum, as usual</a>!