@y.ivanov
You can do whatever you want. If you require slow code and run everything in -O0 on a Z80 abusing of slow IX/IY registers you can of course: my first computer was a 1MHz ZX81 and I wrote on asm on it by poking hexa in REM (!), so I found that CP/M and pascal in your signature was a bit too fast and lazy.
But it is not what we do on production. We need to host as many clients as possible per server. This helps a lot - and also the planet by being more "green".
I specifically wrote where the numbers come from, either Linux x86_64 and our memory manager, or Win32 and the FPC memory manager.
The initial post #43 had an issue about the JSON length used to benchmark fpjson. As soon as I discovered that, I claimed there was a mistake, have been very sorry about it, fixed it, and provided new numbers.
I am sorry if you don't like "marketing" stuff, but I also provided the numbers.
To not be too much marketing, I propose we take a look at the big picture of JSON and its real use.
I think the user/consumer/practical point of view is the point. JSON is needed for real work, not for benchmarks or just validation.
- If the user needs to parse some input, it is most likely that the structure is known. So a dynamic array and DynArrayLoadJson is very easy and efficient, to fill record or dynamic array of class instance (yes it works too with mORMot).
- We use JSON as basic data representation in our ORM, between the objects and the data provider, and also when publishing a DB over REST: we introduced a direct DB access writing JSON from the SQL/NoSQL drivers with no TDataSet in between, for both reading (lists) and writing (even in batch insert/update mode): this is why our ORM could be so fast - faster than TDataSet for individual objects SELECT for instance, or bulk insertion.
- We use JSON as basic data representation in our SOA, for interface-based services. If you know the data structure, any class or record or array would be serialized very efficiently, without creating nodes in memory, but directly filling data structures. If you don't know the data structure, you specify a variant parameter and the JSON will be parsed or written using a TDocVariant custom variant instance.
- On whatever use we may imagine, one huge point about performance is to reduce memory allocation, especially on multi-threaded server process. The whole mORMot code tends to allocate/reallocate as little as possible, to leverage the performance. This is also why we wrote a dedicated MM for x86_64, and why we added unique features like field names (or values) text interning as an option. Because it helps in the real world, even if it is slightly slower in micro benchmarks.
A "JSON library to rule them all" is not so useful in practice. Only in benchmarks you need to parse anything with no context.
If you need to create fpjson or jsontools classes by hand when writing SOA server or client side, it is less convenient than a set of dedicated JSON engines as mORMot does. In fact, even if the nodes are automatically created by the SOA library, it is always slower than a dedicated engine.
So in respect to production code, where performance matters, which is mainly on server side, putting TOrmTableJson results in a benchmark does make sense. And TOrmTableJson is definitively 20 times faster parsing a typical JSON ORM/REST result than fpjson on x86_64. And if the DB emits "not expanded" JSON (array of values instead of array of object), it is 40 times faster in practice because there is less JSON to parse for the same dataset. This 40 times factor is a fact for this realistic dataset.
So here are this morning numbers, on Debian x86_64, from FPC 3.2.0 in -O3 mode:
(people.json = array of 8227 ORM objects, for 1MB file)
StrLen() in 828us, 23.1 GB/s
IsValidUtf8(RawUtf8) in 1.45ms, 13.1 GB/s
IsValidUtf8(PUtf8Char) in 2.21ms, 8.6 GB/s
IsValidJson(RawUtf8) in 21.36ms, 917.7 MB/s
IsValidJson(PUtf8Char) in 20.63ms, 0.9 GB/s
JsonArrayCount(P) in 19.70ms, 0.9 GB/s
JsonArrayCount(P,PMax) in 20.14ms, 0.9 GB/s
JsonObjectPropCount() in 10.54ms, 1 GB/s
TDocVariant in 121.68ms, 161.1 MB/s
TDocVariant no guess in 127.85ms, 153.3 MB/s
TDocVariant dvoInternNames in 147.27ms, 133.1 MB/s
TOrmTableJson expanded in 37.57ms, 521.8 MB/s
TOrmTableJson not expanded in 20.36ms, 423.5 MB/s
(here the time is relevant because the JSON size is smaller: 20.36 ms instead of 777.7 ms)
DynArrayLoadJson in 62.38ms, 314.3 MB/s
fpjson in 77.78ms, 25.2 MB/s
(run 10 times less because it is slower - and yes, the length is also div 10 and correct I hope)
(sample.json with a lot of nested documents)
TDocVariant sample.json in 32.32ms, 405.7 MB/s
TDocVariant sample.json no guess in 31.93ms, 410.6 MB/s
fpjson sample.json in 11.25ms, 116.4 MB/s