
Round 22 of the TechEmpower Frameworks has just finished.
And this time, there was a pascal framework in the race: our little mORMot!
Numbers are quite good, because we are rated #12 among 302 frameworks over 791 runs of several configurations.
2023-10-31
2023-10-31. Open Source › mORMot Framework
Round 22 of the TechEmpower Frameworks has just finished.
And this time, there was a pascal framework in the race: our little mORMot!
Numbers are quite good, because we are rated #12 among 302 frameworks over 791 runs of several configurations.
2022-05-21
2022-05-21. Open Source › mORMot Framework
The HTTP server is one main part of any SOA/REST service, by design.
It is the main entry point of all incoming requests. So it should better be stable and efficient. And should be able to scale in the future, if needed.
There have always been several HTTP servers in mORMot. You can use the HTTP server class you need.
In mORMot 2, we added two new server classes, one for publishing over HTTP, another able to upgrade to WebSockets. The main difference is that they are fully event-driven, so their thread pool is able to scale with thousands of concurrent connections, with a fixed number of threads. They are a response to the limitations of our previous socket server.
2022-01-22
2022-01-22. Open Source › mORMot Framework
To ensure thread-safety, especially on server side, we usually protect code with critical sections, or locks. In recent Delphi revisions, we have the TMonitor
feature, but I would rather trust the OS for locks, which are implemented using Windows Critical Sections, or POSIX futex/mutex.
But all locks are not born equal. Most of the time, the overhead of a Critical Section WinAPI or the pthread
library is not needed.
So, in mORMot 2, we introduced several native locks in addition to those OS locks, with multi-read/single-write abilities, or re-entrancy.
2021-11-16
2021-11-16. Open Source › mORMot Framework
EKON 25 at Düsseldorf was a great conference (konference?).
At last, a physical gathering of Delphi developers, mostly from Germany, but also from Europe - and even some from USA! No more virtual meetings, which may trigger the well known 'Abstract Error' on modern pascal coders.
There were some happy FPC users too - as I am now.
I have published the slides of my conferences, mostly about mORMot 2.
By the way, I wish we would be able to release officially mORMot 2 in December, before Christmas. I think it starts to be stabilized and already known to be used on production. We expect no more breaking change in the next weeks.
2021-08-17
2021-08-17. Open Source › mORMot Framework
Last weeks, we have enhanced mORMot support to one of the more powerful AARM64 CPU available: the Ampere Altra CPU, as made available on the Oracle Cloud Infrastructure.
Long story short, this is an amazing hardware to run on server side, with performance close to what Intel/AMD offers, but with almost linear multi-core scalability. The FPC compiler is able to run good code on it, and our mORMot 2 library is able to use the hardware accelerated opcodes for AES, SHA2, and crc32/crc32c.
2020-05-07
2020-05-07. Open Source › mORMot Framework
As a gift to the FPC community, I just committed a new Memory Manager for FPC.
Check mormot.core.fpcx64mm.pas in our mORMot2 repository.
This is a stand-alone unit for FPC only.
It targets Windows and Linux multi-threaded Service applications - typically mORMot daemons.
It is written in almost pure x86_64 assembly, and some unique tricks in the Delphi/FPC Memory Manager world.
It is based on FastMM4 (not FastMM5), and we didn't follow the path of the FastMM4-AVX version - instead of AVX, we use plain good (non-temporal) SSE2 opcode, and we rely on the mremap API on Linux for very efficient reallocation. Using mremap is perhaps the biggest benefit of this memory manager - it leverages a killer feature of the Linux kernel for sure. By the way, we directly call the Kernel without the need of the libc.
We tuned our x86_64 assembly a lot, and made it cross-platform (Windows and POSIX). We profiled the multi-threading, especially by adding some additional small blocks for GetMem (which is a less expensive notion of "arenas" as used in FastMM5 and most C allocators), introducing an innovatice and very efficient round-robin of tiny blocks (<128 bytes), and proper spinning for FreeMem and medium blocks.
It runs all our regression tests with huge performance and stability - including multi-threaded tests with almost no slow down: sleep is reported as less than 1 ms during a 1 minute test. It has also been validated on some demanding multi-threaded tasks.
2020-02-17
2020-02-17. Open Source › mORMot Framework
Our Open Source framework includes some optimized asm alternatives
to RTL's move()
and fillchar()
, named
MoveFast()
and FillCharFast()
.
We just rewrote from scratch the x86_64 version of those,
which was previously taken from third-party snippets.
The brand new code is meant to be more efficient and maintainable. In
particular, we switched to SIMD 128-bit SSE2 or 256bit AVX memory access (if
available), whereas current version was using 64-bit regular registers. The
small blocks (i.e. < 32 bytes) process occurs very often, e.g. when
processing strings, so has been tuned a lot. Non temporal instructions (i.e.
bypassing the CPU cache) are used for biggest chunks of data. We tested
ERMS support, but it
was found of no benefit in respect to our optimized SIMD, and was actually
slower than our non-temporal variants. So ERMS code is currently disabled in
the source, and may be enabled on demand by a conditional.
FPC move()
was not bad. Delphi's Win64 was far
from optimized - even ERMS was poorly introduced in latest RTL, since it should
be triggered only for blocks > 2KB. Sadly, Delphi doesn't support AVX
assembly yet, so those opcodes would be available only on FPC.
Resulting numbers are talking by themselves. Working on Win64 and Linux, of course.
2016-01-09
2016-01-09. Open Source › mORMot Framework
Once your application is multi-threaded, concurrent data access should be
protected. We already wrote about how debugging multi-thread
applications may be hard.
Otherwise, a "race
condition" issue may appear: for instance, if two threads modify a variable
at the same time (e.g. decrease a counter), values may become incoherent and
unsafe to use. Another symptom of broken logic is the "deadlock", by which the whole
application appears to be blocked and unresponsive, when two threads have a
wrong use of the lock, so are blocking each-others.
On a server system, which is expected to run 24/7 with no maintenance, such
issues are to be avoided.
In Delphi, protection of a resource (which may be an object, or any
variable) is usually done via Critical
Sections.
A critical section is an object used to make sure, that some part of
the code is executed only by one thread at a time. A critical section
needs to be created/initialized before it can be used and be released when it
is not needed anymore. Then, some code is protected using Enter/Leave
methods, which would lock its execution: in practice, only a single
thread would own the critical section, so only a single thread would
be able to execute this code section, and other threads would wait until the
lock is released. For best performance, the protected sections should be as
small as possible - otherwise the benefit of using threads may be voided, since
any other thread would wait for the thread owning the critical section
to release the lock.
We will now see that Delphi's TCriticalSection
may have
potential issues, and what our framework proposes to ease critical
section use in your applications.
2015-09-14
2015-09-14.
Back in 2013, I found out an implementation weakness in the implementation
of ARC weak references in the RTL.
A giant lock
was freezing all threads and cores, so would decrease a lot the performance
abilities of any ARC application, especially in multi thread.
I just investigated that things are now better.
2015-05-14
2015-05-14. Open Source › mORMot Framework
We identified and fixed today several issues which may affect applications creating a lot of threads (i.e. not using a thread pool). The symptom was an unexpected access violation, when you reach a multiple of 256 threads count. You should better upgrade to at least revision 1.18.1351 if your […]
2014-10-24
2014-10-24. Open Source › mORMot Framework
We almost finished implementing a long-standing feature request,
introducing MVC / MVVM for Web Applications (like RubyOnRails) in mORMot.
This is a huge step forward, opening new perspectives not only to our
framework, but for the Delphi community.
In respect to the existing
MVC frameworks for Delphi, our solution is closer to Delphi On Rails (by the
convention-over-configuration
pattern) than the Delphi MVC
Framework or XMM.
The mORMot point of view is unique, and quite powerful,
since it is integrated with other parts of our framework, as its ORM/ODM or interface-based services.
Of course, this is a work in progress, so you are welcome to put your feedback,
patches or new features!
We will now explain how to build a MVC/MVVM web application using
mORMot, starting from the "30
- MVC Server" sample.
First of all,
check the source in our GitHub repository: two .pas
files, and
a set of minimalist Mustache
views.
This little web application publishes a simple BLOG, not fully finished yet
(this is a Sample, remember!).
But you can still execute it in your desktop browser, or any mobile device
(thanks to a simple Bootstrap-based responsive design), and see the
articles list, view one article and its comments, view the author information,
log in and out.
This sample is implemented as such:
MVVM | Source | mORMot |
Model | MVCModel.pas |
TSQLRestServerDB ORM over a SQlite3 database |
View | *.html |
Mustache template engine in the Views sub-folder |
ViewModel | MVCViewModel.pas |
Defined as one IBlogApplication interface |
For the sake of the simplicity, the sample will create some fake data in its own local SQlite3 database, the first time it is executed.
2014-07-12
2014-07-12. Pascal Programming
Cape Cod Gunny just wrote a blog article about how to replace a global variable by a static class instance.
But I had to react!
Using such static declaration is just another way of creating a global
variable.
This is just a global variable in disguise.
In fact, the generated asm will be just like a global variable!
It encapsulates the global declaration within a class name space, but it is
still IMHO a very wrong design.
I've seen so many C# or Java code which used such a pattern (there is no global
variable in those languages), and it has the same disadvantages as global
variables.
Just like the singleton
syndrome,
Code is just not re-entrant nor thread-safe.
Nightmare to debug and let evolve.
2014-06-09
2014-06-09. Pascal Programming
Since there was recently some articles about performance comparison between several versions of the Delphi compiler, we had to react, and gives our personal point of view.
IMHO there won't be any definitive statement about this.
I'm always doubtful about any conclusion which may be achieved with such kind
of benchmarks.
Asking "which compiler is better?" is IMHO a wrong question.
As if there was some "compiler magic": the new compiler will be just like a new
laundry detergent - it will be cleaner and whiter...
Performance is not about marketing.
Performance is an iterative process, always a matter of circumstances,
and implementation.
Circumstances of the benchmark itself.
Each benchmark will report only information about the process it
measured.
What you compare is a limited set of features, running most of the time an
idealized and simplified pattern, which shares nothing with real-world
process.
Implementation is what gives performance.
Changing a compiler will only gives you some percents of time change.
Identifying the true bottlenecks of an application via a profiler, then
changing the implementation of the identified bottlenecks may give order of
magnitudes of speed improvement.
For instance, multi-threading abilities can be achieved by following
some simple rules.
With our huge set of regression tests, we have at hand more than 16,500,000 individual checks, covering low-level features (like numerical and text marshaling), or high-level process (like concurrent client/server and database multi-threaded process).
You will find here some benchmarks run with Delphi 6, 7, 2007, XE4 and XE6
under Win32, and XE4 and XE6 under Win64.
In short, all compilers performs more or less at the same speed.
Win64 is a
little slower than Win32, and the fastest appears to be Delphi 7, using our
enhanced and
optimized RTL.
2014-04-28
2014-04-28. Open Source › Open Source libraries
Mustache is
a well-known logic-less template engine.
There is plenty of Open Source implementations around (including in JavaScript,
which can be very convenient for AJAX applications on client side, for
instance).
For mORMot, we created the first pure Delphi implementation of it,
with a perfect integration with other bricks of the framework.
In last part of this series of blog articles, we will introduce the
Mustache library included within mORMot source code
tree.
You can download this documentation
as one single pdf file.
2014-04-28. Open Source › Open Source libraries
Mustache is a well-known
logic-less template engine.
There is plenty of Open Source implementations around (including in JavaScript,
which can be very convenient for AJAX applications on client side, for
instance).
For mORMot, we created the first pure Delphi implementation of it,
with a perfect integration with other bricks of the framework.
In this second part of this series of blog articles, we will introduce the
Mustache syntax.
You can download this documentation
as one single pdf file.
2014-04-28. Open Source › Open Source libraries
Mustache is a well-known
logic-less template engine.
There is plenty of Open Source implementations around (including in JavaScript,
which can be very convenient for AJAX applications on client side, for
instance).
For mORMot, we created the first pure Delphi implementation of it,
with a perfect integration with other bricks of the framework.
In this first part of this series of blog articles, we will introduce the
Mustache design.
You can download this documentation
as one single pdf file.
2014-04-07
2014-04-07. Open Source › mORMot Framework
As we already
stated, we finished the first step of integration of the
SpiderMonkey engine to our mORMot framework.
Version 1.8.5 of the library is already integrated, and latest official
revision will be soon merged,
thanks to mpv's great contribution.
It can be seen as stable, since it is already used on production site to serve more than
1,000,000 requests per day.
You can now easily uses JavaScript on both client and server side.
On server side, mORMot's implementation offers an unique concept, i.e.
true multi-threading,
which is IMHO a huge enhancement when compared to the regular node.js mono-threaded implementation,
and its callback hell.
In fact, node.js official marketing states its non-blocking scheme is
a plus. It allows to define a HTTP server in a few lines, but huge server
applications need JavaScript experts not to sink into a state a
disgrace.
2014-03-07
2014-03-07. Open Source › mORMot Framework
We just tested, benchmarked and validated Oracle MySQL, IBM DB2 and PostgreSQL support for our SynDB
database classes and the mORMot's ORM core.
This article will also show all updated results, including our newly introduced multi-value
INSERT statement generations, which speed up a lot BATCH insertion.
Stay tuned!
Purpose here is not to say that one library or database is better or faster than another, but publish a snapshot of mORMot persistence layer abilities, depending on each access library.
In this timing, we do not benchmark only the "pure" SQL/DB layer access
(SynDB
units), but the whole Client-Server ORM of our
framework.
Process below includes all aspects of our ORM:
TSQLRecord
instances, via optimized
RTTI;In those tests, we just bypassed the communication layer, since
TSQLRestClient
and TSQLRestServer
are run in-process,
in the same thread - as a TSQLRestServerDB
instance. So you have
here some raw performance testimony of our framework's ORM and RESTful core,
and may expect good scaling abilities when running on high-end hardware, over a
network.
On a recent notebook computer (Core i7 and SSD drive), depending on the back-end database interfaced, mORMot excels in speed, as will show the following benchmark:
DB.pas
based classes), speed is lower (even if comparable for DB2,
MS SQL, PostgreSQL, MySQL) but still enough for most work, due to some
optimizations in the mORMot code (e.g. caching of prepared statements,
SQL multi-values insertion, direct export to/from JSON, SQlite3
virtual mode design, avoid most temporary memory allocation...).Difficult to find a faster ORM, I suspect.
2013-12-05
2013-12-05. Open Source
Do you remember this former article about scalability of the Delphi memory manager, in multi-thread execution context?
Our SynScaleMM is still experimental.
But did pretty well, for an experiment!
At first, you can take a look at ScaleMM2, which is more stable, and based on the same ground.
But a new multi-thread friendly memory manager for Delphi just came
out.
It is in fact the anonymous (and already famous) "NN memory manager"
Primož talked about in his
article about string building and memory managers.
(Note that in this article, our SynScaleMM was found to be scaling
very well, but on the other hand, Primož did compile its benchmark program
in Debug mode, so our TTextWriter
was not in good shape:
when you compile in Release mode, optimizations and inlining are ON,
and our good TTextWriter
just flies... See the note at the
beginning of the article - this is why I never find those benchmarks very
informative. I always prefer profiling from the real world with real useful
process… and was never convinced by any such naive benchmark.)
OK, back to our business!
SapMM is an interesting beast.
https://code.google.com/p/sapmm
Sounds like if Alexei (the initial coder) has a C coding background. But
that's fine when you have to deal with low-level structures and algorithms, as
required by a memory manager. :)
It features everything we may ask for such a piece of code: clear design,
optimized code (mostly by inlining process), memory leak reporting, some
parameters for tuning.
It is only for Delphi XE (and up) under Win32 by now, but contributors are
welcome!
It is used in production since more than half a year, and it passed all
FastcodeMM
benchmark tests.
If you want a direct link of the today's source code, without SVN, you may
try this direct link from
our site.
(but it probably will never be updated - you are warned)
2013-11-04
2013-11-04. Open Source › mORMot Framework
On an recent notebook computer (Core i7 and SSD drive), depending on the back-end database interfaced, mORMot excels in speed:
DB.pas
based classes), speed is lower, but still enough for most
work.Difficult to find a faster ORM, I suspect.
The following tables try to sum up all available possibilities, and give some benchmark (average objects/second for writing or read).
In these tables:
Synchronous := smOff
and/or DB.LockingMode :=
lmExclusive
;TObjectList
' indicates a
TSQLRestServerStaticInMemory
instance, either static (with no SQL
support) or virtual (i.e. SQL featured via SQLite3 virtual table
mechanism) which may persist the data on disk as JSON or compressed
binary;SynDBOracle.pas
);This list of database providers is to be extended in the future. Any feedback is welcome!
Numbers are expressed in rows/second (or objects/second). This benchmark was compiled with Delphi 7, so newer compilers may give even better results, with in-lining and advanced optimizations.
Note that these tests are not about the relative speed of each database engine, but reflect the current status of the integration of several DB libraries within the mORMot database access.
Purpose here is not to say that one library or database is better or faster than another, but publish a snapshot of current mORMot persistence layer abilities.
In this timing, we do not benchmark only the "pure" SQL/DB layer access
(SynDB
units), but the whole Client-Server ORM of our framework:
process below includes read and write RTTI access of a TSQLRecord
,
JSON marshaling, CRUD/REST routing, virtual cross-database layer, SQL
on-the-fly translation. We just bypass the communication layer, since
TSQLRestClient
and TSQLRestServer
are run in-process,
in the same thread - as a TSQLRestServerDB
instance. So you have
here some raw performance testimony of our framework's ORM and RESTful
core.
You can compile the "15 - External DB performance
" supplied
sample code, and run the very same benchmark on your own configuration.
« previous entries - page 1 of 2