You are not logged in.
Hi Arnaud,
I wanted to share some results from a study I recently conducted regarding the scalability of Generics in Delphi.
In large-scale projects, the Delphi compiler often struggles with a massive number of generic specializations. To test the limits, I created a scenario involving 500 distinct record types and over 2,000 collection specializations (Lists and Dictionaries).
The performance of mORMot 2 was impressive:
While the standard RTL took nearly 90 seconds to compile and Spring4D hit the compiler's memory limits (F2046), mORMot 2 (using mormot.core.collections) finished in about 4 seconds. It also produced the smallest binary size among all tested implementations.
It’s remarkable how your implementation maintains such a low overhead even under heavy load.
On a side note: My study also includes a "StaticGenerics" approach using a tool called TmplCodeGen. I wanted to mention that this generator uses your mORMot Mustache implementation to produce the Pascal source files. It’s a very reliable and efficient way to handle code generation.
Thank you for your tireless dedication to the Open Source community. mORMot 2 continues to be a vital resource for Delphi developers who need to push the boundaries of performance and efficiency.
The full benchmark and source code can be found here:
https://github.com/WladiD/WDDelphiTools … ericsStudy
Best regards,
Waldemar Derr
Last edited by WladiD (Yesterday 06:48:30)
Offline
Hello Waldemar,
Very nice findings!
It is true that massive number of generic specializations sometimes matter more than micro benchmarks comparison of a few simple type definitions (in which mORMot 2 may sometimes be behind).
For real applications, once you start using generics in your business code, you use it anywhere, and the compiler and RTL should follow your expectations.
Our generics were designed as a very small layer over our TDynArray or TSynDictionary wrappers, which shine in such situation: most of the code is written once, and shared in TIListParent/TIKeyValueParent abstract ancestors. The "specialization" for each type is only a few lines of code. Also its enumerators are not the absolute fastest, but the smallest possible in code size, using pointer tricks.
These maybe the technical reason why mORMot 2 generics are so efficient about compilation time and executable size.
I also guess that the "static" version includes compiling mORMot itself, since you use it for the actual data process.
You could have also tried with SMALLGENERICS conditional, and I guess it would have been even a bit more compact. ![]()
Another point of interest about mORMot generics is that they are compatible with FPC.
And my guess is that the FPC generics standard library would generate much bigger code than even Delphi or Spring4D, because it was designed for compatibility and exhaustivity, not executable size.
Not to forget that it has some additional features, like JSON or binary built-in serialization, or dictionary thread safety or timeouts.
Perhaps you may post it on DelphiPraxis too, it could be interesting for others!
Thanks again! ![]()
Offline
Hello Arnaud,
Regarding your guess about the "StaticGenerics": Yes, you are absolutely right. This version relies on mormot.core.* units for the actual data storage and processing, so mORMot is indeed part of that compilation as well.
I will definitely follow your suggestion and share the findings on Delphi-Praxis. It is a topic that affects many of us working on larger projects.
Have a nice day and best regards from Germany.
Offline