<?xml version="1.0" encoding="utf-8"?><?xml-stylesheet title="XSL formatting" type="text/xsl" href="http://blog.synopse.info/feed/rss2/xslt" ?><rss version="2.0"
  xmlns:dc="http://purl.org/dc/elements/1.1/"
  xmlns:wfw="http://wellformedweb.org/CommentAPI/"
  xmlns:content="http://purl.org/rss/1.0/modules/content/"
  xmlns:atom="http://www.w3.org/2005/Atom">
<channel>
  <title>Synopse</title>
  <link>http://blog.synopse.info/</link>
  <atom:link href="http://blog.synopse.info:82/feed/rss2" rel="self" type="application/rss+xml"/>
  <description>&quot;Synopse Informatique&quot; Software solutions, and associated open source database and low level components.</description>
  <language>en</language>
  <pubDate>Tue, 21 May 2013 07:03:58 +0200</pubDate>
  <copyright>©2012 Synopse Informatique</copyright>
  <docs>http://blogs.law.harvard.edu/tech/rss</docs>
  <generator>Dotclear</generator>
  
    
  <item>
    <title>Performance issue in NextGen ARC model</title>
    <link>http://blog.synopse.info/post/2013/05/21/Performance-issue-in-NextGen-ARC-model</link>
    <guid isPermaLink="false">urn:md5:f46c63017b15b8d4af58f93a51293060</guid>
    <pubDate>Tue, 21 May 2013 08:55:00 +0200</pubDate>
    <dc:creator>A.Bouchez</dc:creator>
        <category>Pascal Programing</category>
        <category>ARC</category><category>asm</category><category>blog</category><category>CrossPlatform</category><category>Delphi</category><category>GarbageCollector</category><category>performance</category><category>weak pointers</category>    
    <description>&lt;p&gt;Apart from being very slow during compilation, the Delphi &lt;em&gt;NextGen&lt;/em&gt;
compiler introduced a new memory model, named ARC.&lt;/p&gt;
&lt;p&gt;We already spoke about ARC years ago, so please &lt;a href=&quot;http://blog.synopse.info/post/2011/12/08/Avoiding-Garbage-Collector%3A-Delphi-and-Apple-on-the-same-side&quot;&gt;
refer to our corresponding blog article for further information&lt;/a&gt;, especially
about how Apple did introduce ARC to &lt;em&gt;iOS&lt;/em&gt; instead of the Garbage
Collector model.&lt;/p&gt;
&lt;p&gt;About how ARC is to be used in the NextGen compiler, take a look at &lt;a href=&quot;http://blog.marcocantu.com/blog/automatic_reference_counting_for_delphi.html&quot;&gt;Marco's
blog article&lt;/a&gt;, and its linked resources.&lt;/p&gt;
&lt;p&gt;But the ARC model, as implemented by Embarcadero, has at least one huge
performance issue, in the way &lt;a href=&quot;http://blog.synopse.info/post/2012/06/18/Circular-reference-and-zeroing-weak-pointers&quot;&gt;weak
references, and zeroing weak pointers&lt;/a&gt; have been implemented.&lt;br /&gt;
I do not speak about the general slow down introduced during every class/record
initialization/finalization, which is noticeable, but not a big concern.&lt;/p&gt;
&lt;p&gt;If you look at XE4 internals, you will discover
a disappointing &lt;em&gt;global lock&lt;/em&gt; introduced in the RTL.&lt;/p&gt;    &lt;p&gt;The main issue is that XE4 RTL implements weak references with a &lt;em&gt;global
lock&lt;/em&gt;, which will slow down the whole process a lot, especially in
multi-thread.&lt;/p&gt;
&lt;pre&gt;
&lt;code&gt;procedure TInstHashMap.RegisterWeakRef(Address: Pointer; Instance: Pointer);
var
  H: Integer;
  Item: PInstItem;
begin
  Lock;
  try
    H := Hash(Instance);
    Item := FindInstItem(Instance, H);
    if Item = nil then
      Item := AddInstItem(Instance, H);
    Item.RegisterWeakRef(Address);
  finally
    Unlock;
  end;
end;
&lt;/code&gt;
&lt;/pre&gt;
&lt;p&gt;The &lt;code&gt;Lock/Unlock&lt;/code&gt; methods are implemented via
&lt;code&gt;TMonitor&lt;/code&gt;.&lt;br /&gt;
This synchronization class has the benefit to be cross-platform, but the
drawback of &lt;a href=&quot;http://www.thedelphigeek.com/2011/05/lock-free-vs-locking.html&quot;&gt;being slower
than other approaches&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Such a global lock will just kill the performance in multi-thread
process.&lt;/p&gt;
&lt;p&gt;Our weak pointer implementation for interfaces in &lt;ins&gt;&lt;em&gt;mORMot&lt;/em&gt;&lt;/ins&gt;
uses a diverse approach, with a list per class type and small critical
sections, so will be much more multi-thread friendly than XE4's
implementation.&lt;/p&gt;
&lt;p&gt;We can use ARC when targeting mobile platforms.&lt;br /&gt;
But in its current implementation, ARC would be a disaster about performance
for a server application.&lt;/p&gt;
&lt;p&gt;I'm waiting for XE5!&lt;/p&gt;
&lt;p&gt;Please do not kill Delphi desktop/server application performance!&lt;/p&gt;
&lt;p&gt;In October last year &lt;a href=&quot;http://blog.synopse.info/post/2012/10/06/Delphi-XE3-is-preparing-reference-counting-for-class-instances&quot;&gt;
we were already speaking about this global lock implementation issue&lt;/a&gt;, when
we discovered a pre-version of it in the XE3 RTL source code.&lt;br /&gt;
And the version shipped with XE4 did not improve anything.&lt;br /&gt;
How could EMB say that performance is a concern for them?&lt;br /&gt;
The more I see it, the more I think that enforcing strings to be immutable for
performance reasons is just a joke, when you look at the current RTL state.&lt;/p&gt;</description>
    
    
    
      </item>
    
  <item>
    <title>Are we the milch cow of Embarcadero?</title>
    <link>http://blog.synopse.info/post/2013/05/20/Are-we-the-milch-cow-of-Embarcadero</link>
    <guid isPermaLink="false">urn:md5:45a95a94fd5a4ce3a9e6779bb8f8d787</guid>
    <pubDate>Mon, 20 May 2013 11:23:00 +0200</pubDate>
    <dc:creator>A.Bouchez</dc:creator>
        <category>Pascal Programing</category>
        <category>blog</category><category>CrossPlatform</category><category>Delphi</category><category>NextGen</category><category>performance</category><category>Source</category><category>string</category>    
    <description>&lt;p&gt;So &lt;a href=&quot;http://blog.marcocantu.com/blog/strings_immutability_cow_ansistrings.html&quot;&gt;Marco
did answer&lt;/a&gt; to &lt;a href=&quot;http://blog.synopse.info/post/2013/05/11/Delphi-XE4-NextGen-compiler-is-disapointing&quot;&gt;our blog
article&lt;/a&gt;.&lt;br /&gt;
Thanks a lot for taking your time, Marco!&lt;br /&gt;
I knew you are an open minded fellow.&lt;/p&gt;
&lt;p&gt;When I read this Marco's proposal to make an Open Source third-party library
to support &lt;em&gt;AnsiStrings&lt;/em&gt;, I was stunned.&lt;/p&gt;
&lt;p&gt;This demonstrates a naive (and I know he is not such a guy) misunderstanding
of what Open Source is.&lt;br /&gt;
Open Source is not the milch cow of big Companies.&lt;br /&gt;
Open Source is not the solution when you do not want to fix their own
problems.&lt;/p&gt;
&lt;p&gt;Marco is fair enough to propose his own contribution to the project.&lt;br /&gt;
But why on earth won't they make it part of the official RTL?&lt;br /&gt;
But why on earth wouldn't they make it compiler-supported, as it always
was?&lt;br /&gt;
It is 100% part of their duty.&lt;/p&gt;
&lt;p&gt;I understand the fact that &lt;em&gt;Extended&lt;/em&gt; was not supported any more at
compiler level in Win64.&lt;br /&gt;
It did make sense at compiler level (SSE2 only supports single or
double).&lt;br /&gt;
And some third party users proposed a third party library to handle it via
records.&lt;/p&gt;
&lt;p&gt;But for such low-level feature as &lt;em&gt;AnsiString&lt;/em&gt;, since there was no
compiler-level nor CPU-level explanation, I do not see any reason to get rid of
it.&lt;br /&gt;
LLVM is perfectly able to handle both &lt;em&gt;AnsiString&lt;/em&gt; and
&lt;em&gt;UnicodeString&lt;/em&gt;, with the COW paradigm.&lt;/p&gt;    &lt;h4&gt;Open Source&lt;/h4&gt;
&lt;p&gt;IMHO the main point about Open Source is not it is free (as a beer), but
that it is free (as a bird).&lt;/p&gt;
&lt;p&gt;I mean, the community is always worth consulting and learning from.&lt;br /&gt;
I mean, you can contribute to the project, from the internals, if you are good
enough.&lt;br /&gt;
I mean, if you do not like the roadmap or orientation, you are free to fork the
project.&lt;/p&gt;
&lt;h4&gt;Milch cow&lt;/h4&gt;
&lt;p&gt;Marco's answer sounded to me as:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&amp;quot;OK. I admit I'm not so happy with this breaking change.&lt;br /&gt;
But we do not want to maintain the existing code base.&lt;br /&gt;
We do want to make our life easier.&lt;br /&gt;
So we get rid of &lt;em&gt;AnsiString/RawByteString/UTF8String&lt;/em&gt;.&lt;br /&gt;
If some of you are hurt and will loose a lot of money because of OUR decision,
let's do together a workaround, with performance penalties, and we will sleep
well tonight&amp;quot;.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Andreas Hausladen did great work on fixing IDEs.&lt;br /&gt;
His work is not Open Source (some part is), but his process sounds just
familiar to the one suggested by Marco.&lt;br /&gt;
Someone is doing EMB's work to fix their mistakes.&lt;br /&gt;
BTW Andy, why is there no fix pack for XE4 yet?&lt;/p&gt;
&lt;h4&gt;Performance penalties&lt;/h4&gt;
&lt;p&gt;Implementing a &lt;em&gt;string&lt;/em&gt; type with a &lt;em&gt;record&lt;/em&gt; type and a nested
&lt;code&gt;TBytes&lt;/code&gt; will be definitively slower than the previous
implementation, for several obvious reasons:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;You will loose the COW pattern (&lt;em&gt;TBytes&lt;/em&gt; &lt;a href=&quot;http://delphitools.info/2013/05/13/immutable-strings-in-delphi&quot;&gt;only have
reference counting&lt;/a&gt;);&lt;/li&gt;
&lt;li&gt;You will loose a lot of compiler magic;&lt;/li&gt;
&lt;li&gt;All &lt;em&gt;TBytes&lt;/em&gt; are first filled with 0 whereas &lt;em&gt;AnsiStrings&lt;/em&gt;
are not (and do not need to - only the latest byte needs to be 0);&lt;/li&gt;
&lt;li&gt;&lt;em&gt;Record&lt;/em&gt; initialization, finalization and assignments were never
optimized for speed in the Delphi compiler and RTL.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;IDE integration&lt;/h4&gt;
&lt;p&gt;Since we are requested to do EMB's work, do not forget to write some
debugger extension for the Delphi IDE.&lt;/p&gt;
&lt;p&gt;In fact, we need a mean of seeing a string content, with characters, and not
a set of bytes, when we are debugging our new &lt;em&gt;AnsiString&lt;/em&gt; type.&lt;/p&gt;
&lt;h4&gt;NextGen is SlowGen&lt;/h4&gt;
&lt;p&gt;By the way, I was stunned when I saw how &lt;em&gt;slow&lt;/em&gt; was the
so-called &lt;em&gt;NextGen&lt;/em&gt; Compiler.&lt;/p&gt;
&lt;p&gt;I do not know if it is the new front-end or the LLVM back-end which is so
slow, but the &lt;em&gt;NextGen&lt;/em&gt; compiler is more than 10 or 20 times slower than
the Win32 compiler!&lt;br /&gt;
The Win64 edition was already slower, but to a certain extend.&lt;br /&gt;
I did not make accurate benchmark, but it sounds just another regression.&lt;/p&gt;
&lt;p&gt;Compilation speed is another big advantage of Delphi which is just voided by
this &lt;em&gt;NextGen&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;If I wanted something slow, I would use Visual Studio and C#.&lt;br /&gt;
In comparison, my Delphi compiler was &lt;em&gt;so fast&lt;/em&gt;.&lt;br /&gt;
OK, I admit I may abuse of the &amp;quot;build all&amp;quot; feature. Some kind of superstition,
I guess...&lt;br /&gt;
Working on both C# and Delphi everyday, I'm still so pleased when I switch to
Delphi, and let full projects compiled almost with no delay.&lt;/p&gt;
&lt;h4&gt;Conclusion&lt;/h4&gt;
&lt;p&gt;Marco's answer did not solve any issue of my previous post.&lt;/p&gt;
&lt;p&gt;I never wrote that it would not be possible to replace &lt;em&gt;AnsiChar&lt;/em&gt; by
&lt;em&gt;Byte&lt;/em&gt;.&lt;br /&gt;
I wrote it would be difficult to migrate, slower, and less convenient.&lt;br /&gt;
What we expect is to have such support at compiler level.&lt;/p&gt;
&lt;p&gt;And now I'm convinced that I will have to pay twice: first to buy new Delphi
version (and even more for the new Mobile target), then to spend time
developing / debugging / maintaining what they do not want do do.&lt;/p&gt;
&lt;p&gt;Fair enough?&lt;/p&gt;</description>
    
    
    
      </item>
    
  <item>
    <title>&quot;The shorter code, the better?&quot;</title>
    <link>http://blog.synopse.info/post/2013/05/19/%22The-shorter-code%2C-the-better%22</link>
    <guid isPermaLink="false">urn:md5:2885cae8c5a69c10537685ceab1661aa</guid>
    <pubDate>Sun, 19 May 2013 13:24:00 +0200</pubDate>
    <dc:creator>A.Bouchez</dc:creator>
        <category>Pascal Programing</category>
        <category>ARC</category><category>blog</category><category>Delphi</category><category>GarbageCollector</category><category>GoodPractice</category><category>performance</category><category>weak pointers</category>    
    <description>&lt;p&gt;One quick Sunday post, &lt;a href=&quot;http://tech.turbu-rpg.com/505/how-to-simplify-memory-management-the-right-way&quot;&gt;
from a comment I wrote in a blog article&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I'm always wondering why a lot of programmers tend to implicitly assume that
&amp;quot;the shorter source code, the better&amp;quot;.&lt;/p&gt;
&lt;p&gt;It is true when it means that with proper code refactoring, making small
objects with dedicated methods, the code of your methods will be smaller.&lt;br /&gt;
It is true when you do not like to write as a &amp;quot;Copy &amp;amp; Paste&amp;quot; coder, without
searching to put common code in shared places.&lt;/p&gt;
&lt;p&gt;But is it true at the language level?&lt;br /&gt;
I mean, is it just because your ARC or GC model allow you not to manage the
object memory, that it is always better?&lt;/p&gt;
&lt;p&gt;Just some ideas...&lt;/p&gt;    &lt;h4&gt;1. Delphi interface types already allow to write such short code&lt;/h4&gt;
&lt;p&gt;First of all, it’s worth saying that you can use interfaces to write
perfectly safe and short code, without ARC, just with the current version of
Delphi.&lt;br /&gt;
See for instance how is implemented &lt;a href=&quot;http://www.bilsen.com/gdiplus/index.shtml&quot;&gt;this GDI+ library&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Implicit &lt;code&gt;try..finally free&lt;/code&gt; blocks are already written by the
compiler.&lt;/p&gt;
&lt;p&gt;See also &lt;a href=&quot;http://blog.synopse.info/post/2012/02/29/Delphi-and-interfaces&quot;&gt;our reference
article about interfaces&lt;/a&gt;.&lt;/p&gt;
&lt;h4&gt;2. Delphi Owner property already allows you to manage object life time in
the VCL&lt;/h4&gt;
&lt;p&gt;The whole Delphi components life time is based on &lt;em&gt;ownership&lt;/em&gt;.&lt;br /&gt;
A form &lt;em&gt;owns&lt;/em&gt; its sub components.&lt;br /&gt;
A module &lt;em&gt;owns&lt;/em&gt; its sub components.&lt;br /&gt;
And so on...&lt;/p&gt;
&lt;p&gt;It is when the owner is freed, that all its components are also
released.&lt;/p&gt;
&lt;p&gt;Nice and easy.&lt;br /&gt;
Safe and efficient.&lt;/p&gt;
&lt;h4&gt;3. Code length does not make it less readable&lt;/h4&gt;
&lt;p&gt;We all know that we read much more code than we write.&lt;/p&gt;
&lt;p&gt;So first priority is to let the code be as readable as possible.&lt;br /&gt;
IMHO &lt;em&gt;try…finally free&lt;/em&gt; patterns do not pollute
the readability of the code.&lt;br /&gt;
On the contrary, from my own taste, it shows exact scope of a class instance
life time.&lt;/p&gt;
&lt;h4&gt;4. Managing life time objects can help you write better code&lt;/h4&gt;
&lt;p&gt;When you manage the object life time, you are not tempted to re-create the
same again and again. You factorize, optimize your code. And it results… in
faster code.&lt;/p&gt;
&lt;p&gt;I have seen plenty of Java and C# programmers how do not give a clue about
memory allocation and internal process: they write code which works, without
asking themselves what will be executed in fact.&lt;br /&gt;
Then, especially on a server side, performance scaling is a nightmare.&lt;br /&gt;
It works on the developer PC, but won't pass the first performance tests
pass.&lt;/p&gt;
&lt;p&gt;Having to manage memory life time by hand does not bother me.&lt;br /&gt;
On the contrary, it made me a better (less bad) lazy programmer.&lt;br /&gt;
And it helped me write faster code, which I know what it is doing when
executed.&lt;/p&gt;
&lt;p&gt;Of course, it is not automatic.&lt;br /&gt;
You can just write &lt;em&gt;try…finally&lt;/em&gt; blocks and weep, without searching for
code refactoring.&lt;br /&gt;
I have seen Delphi code written like that, especially from programmers with a
GC model background.&lt;/p&gt;
&lt;p&gt;So do not be afraid to learn how to manage your memory!&lt;/p&gt;
&lt;h4&gt;5. Managing life time objects is worth learning&lt;/h4&gt;
&lt;p&gt;I was a bit afraid about managing memory, when I came from old BASIC and ASM
programming on 8 bit systems (good old days!).&lt;br /&gt;
A time where there was no heap, but only static allocation, with less than 64
KB of RAM.&lt;br /&gt;
It was working well. And such programs can run for years without any memory
leak!&lt;/p&gt;
&lt;p&gt;But managing life time is a good way of known how your objects are
implemented.&lt;br /&gt;
When using an object method, you are not just getting the right result, you are
calling perhaps a lot of process.&lt;br /&gt;
Worth looking at the internals.&lt;/p&gt;
&lt;p&gt;In practice, when writing efficient code, in a GC world, you will have to
learn a lot of unofficial information from the runtime designers, to know how
GC is implemented.&lt;br /&gt;
As such, performance may vary on one revision of the runtime engine, in
comparison to another.&lt;br /&gt;
If you manage your object life time by hand, you know what you are doing.&lt;/p&gt;
&lt;p&gt;The ARC model is in the middle.&lt;br /&gt;
But introduces some issues, like &lt;a href=&quot;http://blog.synopse.info/post/2012/06/18/Circular-reference-and-zeroing-weak-pointers&quot;&gt;need for weak
references, and zeroing weak pointers&lt;/a&gt;.&lt;br /&gt;
AFAIK the RTL implements weak references with a global lock using the very slow
&lt;code&gt;TMonitor&lt;/code&gt;, which will slow down the whole process a lot, especially
in multi-thread (whereas &lt;a href=&quot;http://blog.synopse.info/post/2012/06/18/Circular-reference-and-zeroing-weak-pointers&quot;&gt;the &lt;em&gt;weak
pointer&lt;/em&gt; implementation in &lt;em&gt;mORMot&lt;/em&gt; core&lt;/a&gt; is much more
scalable, by the way).&lt;br /&gt;
BTW, in October last year &lt;a href=&quot;http://blog.synopse.info/post/2012/10/06/Delphi-XE3-is-preparing-reference-counting-for-class-instances&quot;&gt;
I was already speaking about this global lock implementation issue&lt;/a&gt;, when I
discovered a pre-version of it in the XE3 RTL source code. And the version
shipped with XE4 did not improve anything.&lt;br /&gt;
And could they say that performance is a concern for them? Forcing the
immutable strings use for performance is a just joke, when you look at the
current RTL.&lt;/p&gt;
&lt;h4&gt;6. Source code size has nothing to do with execution speed&lt;/h4&gt;
&lt;p&gt;In practice, the more the compiler magic or the runtime will execute under
the hood, the slower it will be.&lt;br /&gt;
So shorter code is most of the time slower code.&lt;/p&gt;
&lt;p&gt;Of course, I know that using some high-level structures (like a hashed
dictionary or an optimized sort) can be much faster than using a manual search
(with a &lt;code&gt;for ...&lt;/code&gt; loop), or writing a naive bubble sort.&lt;br /&gt;
It does not mean that the more verbose code means the faster.&lt;br /&gt;
But my point is that if you rely on some hidden low-level mechanisms, like
memory handling, auto-generated structures (like closures), or some RTTI-based
features, you will probably write less code, but it will be slower, or less
stable.&lt;/p&gt;
&lt;p&gt;If you do not handle memory, you are not able to tune the execution process,
when needed.&lt;br /&gt;
It is not for nothing that the most speed-effective Java projects just use POJO
and statically allocated instances, to by-pass the GC.&lt;/p&gt;
&lt;p&gt;Worth some minutes thinking about...&lt;/p&gt;</description>
    
    
    
      </item>
    
  <item>
    <title>Delphi XE4 NextGen compiler: using byte instead of ansichar?</title>
    <link>http://blog.synopse.info/post/2013/05/11/Delphi-XE4-NextGen-compiler-is-disapointing</link>
    <guid isPermaLink="false">urn:md5:054213d3bd0696b5a5a69a47f650bf4a</guid>
    <pubDate>Sat, 11 May 2013 10:59:00 +0200</pubDate>
    <dc:creator>A.Bouchez</dc:creator>
        <category>Pascal Programing</category>
        <category>64bit</category><category>AJAX</category><category>Arabic</category><category>ARC</category><category>blog</category><category>C</category><category>CrossPlatform</category><category>Database</category><category>Delphi</category><category>dynamic array</category><category>FireMonkey</category><category>FreePascal</category><category>GarbageCollector</category><category>generics</category><category>interface</category><category>mORMot</category><category>NextGen</category><category>object</category><category>Parsing</category><category>performance</category><category>RAD</category><category>Source</category><category>string</category><category>syntax</category><category>Unicode</category>    
    <description>&lt;p&gt;When I first read &lt;a href=&quot;http://www.embarcadero.com/resources/white-papers/application-development&quot;&gt;the
technical white paper covering all of the language changes in XE4 for mobile
development (tied to the new ARM LLVM-based Delphi compiler)&lt;/a&gt;, I have to
confess I was pretty much confused.&lt;/p&gt;
&lt;p&gt;Two great &lt;a href=&quot;http://synopse.info/forum/viewtopic.php?id=1256&quot;&gt;&lt;em&gt;mORMot&lt;/em&gt; users&lt;/a&gt;
just asked for XE4/iOS support of &lt;em&gt;mORMot&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Win32/Win64 support for XE4 will be done as soon as we got a copy of
it.&lt;br /&gt;
I suspect the code already works, since it was working as expected with XE3,
and we rely on our own set of low-level functions for most internal work.&lt;/p&gt;
&lt;p&gt;But iOS-targetting is more complex, due to the NextGen compiler, mainly.&lt;/p&gt;    &lt;h3&gt;FireMonkey&lt;/h3&gt;
&lt;p&gt;It is first time we are explicitly asked for non-Windows support of
&lt;em&gt;mORMot&lt;/em&gt;.&lt;br /&gt;
This is the reason why we did not put the cross-platform item of the roadmap at
first place.&lt;/p&gt;
&lt;p&gt;We did not do any support for this yet, because:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;No one did ask for cross-platform use of &lt;em&gt;mORMot&lt;/em&gt;;&lt;/li&gt;
&lt;li&gt;FireMonkey was broken several times, has some part of it very poorly
written, and do not support L2R languages - is it mature enough?&lt;/li&gt;
&lt;li&gt;iOS support was broken once - and I prefer FPC to this NextGen compiler
(see below);&lt;/li&gt;
&lt;li&gt;We do not use FireMonkey in any of our applications;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://smartmobilestudio.com/&quot;&gt;SmartMobileStudio&lt;/a&gt; is an
innovative, fast growing, cheap, and stable alternative (with lack of
documentation and 3rd party components, I admit);&lt;/li&gt;
&lt;li&gt;We also considered &lt;a href=&quot;http://twinforms.com/products/wxformsdelphi/index.php&quot;&gt;WxForms&lt;/a&gt; (which
seems not supported any more, but did work well);&lt;/li&gt;
&lt;li&gt;Linux support is a goal for &lt;em&gt;mORMot&lt;/em&gt;, on the server side.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Immutable non-AnsiString&lt;/h3&gt;
&lt;p&gt;Immutable strings are something I do not understand well, in the context of
Delphi.  &lt;/p&gt;
&lt;p&gt;I still do not understand any benefit, in comparison to the &lt;em&gt;&lt;a href=&quot;http://en.wikipedia.org/wiki/Copy-on-write&quot;&gt;copy-on-write&lt;/a&gt;&lt;/em&gt; paradigm
(COW) implemented in Delphi since the beginning for reference-counted value
types.&lt;br /&gt;
With COW, you have the advantages of immutable strings and private copies and
in-place modification, if needed, e.g. for fast parsing.&lt;br /&gt;
COW can allow your text buffer access to be safe &lt;em&gt;and&lt;/em&gt; fast at the same
time. &lt;/p&gt;
&lt;p&gt;Using &amp;quot;&lt;em&gt;array of byte&lt;/em&gt;&amp;quot; as a workaround from
&lt;em&gt;AnsiString/RawByteString&lt;/em&gt; is possible, but will be slower and less
convenient.&lt;br /&gt;
It will implements COW (if &lt;code&gt;const&lt;/code&gt; is used as expected in method
parameters), but it will fill the content with zeros, so slow down the
process.&lt;br /&gt;
And it won't be displayed as text in the debugger, nor allow direct conversion
to string.&lt;br /&gt;
&lt;br /&gt;
Honestly, changing from everything from &lt;em&gt;AnsiChar&lt;/em&gt; to &lt;em&gt;Byte&lt;/em&gt; is
just an awful workaround and breaking change.&lt;br /&gt;
Just like a regression from the modern/turbo Pascal paradigm to a low-level C
data type.&lt;/p&gt;
&lt;p&gt;The switch introduced by NextGen/ARM/LLVM is IMHO much bigger than the one
introduced with Delphi 2009.&lt;br /&gt;
For instance, for third party libraries (like our Open Source &lt;em&gt;mORMot&lt;/em&gt;),
you can maintain an existing code base for all versions of Delphi (e.g. Delphi
6 up to XE4), but you will have to maintain two versions of the code (or nest
it with IFDEF) if you want to support NextGen syntax.&lt;/p&gt;
&lt;p&gt;I understand that conversion to NextGen compiler can be easy. &lt;/p&gt;
&lt;p&gt;See for instance &lt;a href=&quot;http://www.tmssoftware.com/site/blog.asp?post=263&quot;&gt;how TMS reported it to be
not difficult for Aurelius&lt;/a&gt;.&lt;br /&gt;
But... do not forget that it may be on the depend of the performance.&lt;br /&gt;
Using pointers is not evil, if done with knowledge of it.&lt;br /&gt;
See &lt;a href=&quot;http://synopse.info/forum/viewtopic.php?pid=6363#p6363&quot;&gt;this user
feedback about FireBird ODBC access using Aurelius or our Open Source
&lt;em&gt;mORMot&lt;/em&gt;&lt;/a&gt; (which allows remote access, by the way, in addition to
plain ORM).&lt;/p&gt;
&lt;p&gt;IMHO this is one of the great features of compiled object pascal, in
comparison to managed code, or the &amp;quot;NextGen&amp;quot; model.&lt;br /&gt;
My point is that pointers are not evil, especially for performance.&lt;br /&gt;
Of course, I'm speaking about typed pointers, not blank untyped pointers.&lt;/p&gt;
&lt;h3&gt;Huge code modification... for nothing?&lt;/h3&gt;
&lt;p&gt;We could switch the &lt;em&gt;mORMot&lt;/em&gt; code to be Next-Gen compatible, but
since we use UTF-8 at the lowest level, it will need a lot of IFDEF.&lt;br /&gt;
Using &amp;quot;&lt;em&gt;array of byte&lt;/em&gt;&amp;quot; instead of &amp;quot;&lt;em&gt;AnsiString(CP_UTF8)&lt;/em&gt;&amp;quot; and
&amp;quot;&lt;em&gt;byte&lt;/em&gt;&amp;quot; instead of &amp;quot;&lt;em&gt;AnsiChar&lt;/em&gt;&amp;quot; is just an awful regression and
compatibility break.&lt;/p&gt;
&lt;p&gt;We would have to use a lot of function wrappers, or perhaps re-create at
hand a UTF-8 compatibility layer.&lt;br /&gt;
The whole &lt;em&gt;mORMot&lt;/em&gt; core is depending on UTF-8, and IMHO this was *not* a
wrong choice, on the contrary.&lt;/p&gt;
&lt;h3&gt;But why go in this direction?&lt;/h3&gt;
&lt;p&gt;I'm confused with the Embarcadero NextGen compiler. &lt;br /&gt;
Performance is not a goal. The RTL is just worse at every Delphi version.&lt;br /&gt;
... and compilation time is just dead slow, in comparison to the &amp;quot;PreviousGen&amp;quot;
compiler. More than 20 times slower.&lt;br /&gt;
Is it worth it?&lt;/p&gt;
&lt;p&gt;Deprecation of &lt;em&gt;AnsiString&lt;/em&gt; was never prepared by Embarcadero.&lt;br /&gt;
We knew it about &lt;em&gt;shortstring&lt;/em&gt; - OK.&lt;br /&gt;
We were told that the &lt;em&gt;with&lt;/em&gt; keyword is the root of all evil, and should
be avoided - OK.&lt;br /&gt;
But deprecation of &lt;em&gt;AnsiString&lt;/em&gt; in the NextGen compiler sounds like a
showstopper to me.&lt;/p&gt;
&lt;p&gt;And don't tell me it is required by the LLVM compiler to have immutable
strings and UTF-16 encoding.&lt;br /&gt;
This is a pure Embarcadero choice.&lt;/p&gt;
&lt;p&gt;And don't tell me it is for performance optimization.&lt;br /&gt;
The Delphi RTL can be dead slow and not scalable.&lt;br /&gt;
Current string process was not the main speed bottleneck.&lt;br /&gt;
And you have &lt;a href=&quot;http://blog.synopse.info/post/2011/05/20/How-to-write-fast-multi-thread-Delphi-applications&quot;&gt;easy
alternatives to circumvent those bottlenecks and unleash your CPU
power&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;And do not tell me that &lt;em&gt;TStringBuilder&lt;/em&gt; is the answer.&lt;br /&gt;
In-place parsing of buffers is the &lt;a href=&quot;http://blog.synopse.info/post/2011/06/02/Fast-JSON-parsing&quot;&gt;fastest mean e.g. for JSON or XML
performance&lt;/a&gt;.&lt;br /&gt;
&lt;em&gt;TStringBuilder&lt;/em&gt; just replaces classic string concatenation of mutable
strings associated with a modern memory manager.&lt;br /&gt;
It is a workaround to circumvent a performance problem. There is no benefit of
using it.&lt;/p&gt;
&lt;p&gt;I was impressed by the &lt;a href=&quot;http://blog.synopse.info/post/2013/03/07/64-bit-compatibility-of-mORMot-core-units&quot;&gt;Win64 support of
latest versions of Delphi&lt;/a&gt;.&lt;br /&gt;
Very small breaking changes, when adapting &lt;em&gt;mORMot&lt;/em&gt; to this
platform.&lt;br /&gt;
IDE stable enough.&lt;br /&gt;
Resulting executable fast enough (at least when it relies on our SynCommons
unit, and with &lt;a href=&quot;http://blog.synopse.info/post/2013/03/13/x64-optimized-asm-of-FillChar%28%29-and-Move%28%29-for-Win64&quot;&gt;
some tuned asm code&lt;/a&gt;).&lt;br /&gt;
Even nice features where re-introduced into the compiler, after a complain in
the newsgroups, like ability to compile x64 assembler functions/methods.&lt;br /&gt;
But here, I do not understand the direction.&lt;/p&gt;
&lt;h3&gt;Future Object Pascal&lt;/h3&gt;
&lt;p&gt;I do not want Delphi to be another managed-but-compiled language.&lt;br /&gt;
I like the object pascal language because:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;It has the benefits of high-level languages like C# or Java,
with readability, strong typing, classes, generics, interfaces, dedicated
(ansi/wide)char type, string and dynamic array reference counted types;&lt;/li&gt;
&lt;li&gt;It has some nice features I miss in C# for instance, like sets, enumerates
or array of enumerations;&lt;/li&gt;
&lt;li&gt;The unit layout, with clear distinction between &lt;em&gt;interface&lt;/em&gt; and
&lt;em&gt;implementation&lt;/em&gt; sections, is very powerful, in respect to C# or
Java all-in-one syntax;&lt;/li&gt;
&lt;li&gt;It has the low-level power of C, if needed, especially for the library
cores;&lt;/li&gt;
&lt;li&gt;It has a truly working class system (you can use &lt;code&gt;TMyClassClass =
class of TMyClass&lt;/code&gt; with success);&lt;/li&gt;
&lt;li&gt;It has a strong typing paradigm, which mitigates e.g. the use of
&lt;em&gt;pointer&lt;/em&gt;;&lt;/li&gt;
&lt;li&gt;Memory can be managed just as we need, with no Garbage Collector
glitches;&lt;/li&gt;
&lt;li&gt;We have the whole RTL source code at hand, still readable (the C# RTL is
much bigger and complex);&lt;/li&gt;
&lt;li&gt;It compiles very quickly, even for huge projects;&lt;/li&gt;
&lt;li&gt;It generates stand-alone applications, &lt;a href=&quot;http://blog.synopse.info/post/2010/09/20/Dll-hell%2C-WinSXS-directory-and-Delphi-paradise&quot;&gt;with no dll
hell&lt;/a&gt;;&lt;/li&gt;
&lt;li&gt;It has a strong backward compatible history, with huge code available on
the Internet.&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;If I want a C# or Java syntax, I would switch to those.&lt;br /&gt;
Trying to make Delphi more C#-like is a mistake.&lt;br /&gt;
Just think how the attributes syntax in modern Delphi is not pascal-oriented:
it should be defined after the type definition, as in the free pascal syntax,
not before it, as in C#/Java.&lt;/div&gt;
&lt;h3&gt;Please fix NextGen roadmap!&lt;/h3&gt;
&lt;p&gt;Using &lt;em&gt;byte&lt;/em&gt; instead of &lt;em&gt;AnsiChar&lt;/em&gt; is IMHO not a
feature.&lt;br /&gt;
This is not &amp;quot;next generation&amp;quot;.&lt;br /&gt;
This is a regression.&lt;br /&gt;
This is a breaking show-stopper.&lt;/p&gt;
&lt;p&gt;I suspect (hope?) Embarcadero will be clever enough to
re-introduce &lt;em&gt;AnsiString &lt;/em&gt;process to their compiler.&lt;br /&gt;
Forget about zero-based strings.&lt;br /&gt;
Allow mutable strings and pointer access to their buffer.&lt;/p&gt;
&lt;p&gt;Otherwise, I honestly do not have much hope of continuing in this
direction.&lt;br /&gt;
Not worth it.&lt;/p&gt;
&lt;p&gt;The &amp;quot;next gen&amp;quot; object pascal is not C#.&lt;br /&gt;
It may be the Oxygene compiler, even if I do not find so appealing a
cross-compiler language with no cross-platform library.&lt;br /&gt;
It may either be FreePascal and its FCL/RTL, when targeting native
compilation.&lt;br /&gt;
Either DelphiWebScript / SmartMobileStudio, when targeting interpreted / JIT /
JavaScript platforms.&lt;/p&gt;
&lt;h3&gt;Your feedback is needed!&lt;/h3&gt;
&lt;p&gt;I understand that I may be one of the last one using Delphi as such.&lt;br /&gt;
That is, using Delphi not as a RAD tool, but as a strong platform to build huge
applications.&lt;br /&gt;
With some unique benefits, in regard to alternatives (mainly Java or C#).&lt;br /&gt;
Huge list of users of &lt;em&gt;mORMot&lt;/em&gt;, and continuous feedback on the forum,
tends to prove that I'm not the only one!&lt;/p&gt;
&lt;p&gt;Knowing that x64 assembler was re-introduced to Win64 compiler.&lt;br /&gt;
That Client-Server licensing was re-allowed after some newsgroup protest.&lt;/p&gt;
&lt;p&gt;I do not want to troll, just to let Delphi have a long life!&lt;br /&gt;
I like Delphi, I do not want to stay with Delphi 7 for ever, I want the
platform to be maintained and evolving!&lt;br /&gt;
But this NextGen roadmap may kill my hope, and switch to FPC and SMS.&lt;/p&gt;
&lt;p&gt;Feedback is &lt;a href=&quot;http://synopse.info/forum/viewtopic.php?id=1256&quot;&gt;welcome on our forum&lt;/a&gt;!&lt;/p&gt;
&lt;p&gt;Or even better please &lt;a href=&quot;https://forums.embarcadero.com/thread.jspa?threadID=87171&quot;&gt;react on the
Embarcadero forum directly&lt;/a&gt;!&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Update&lt;/em&gt;: a lot of &amp;quot;reaction&amp;quot; did occur in the Embarcadero
forum.&lt;br /&gt;
But no Embarcadero official did react by now.&lt;br /&gt;
Even Team-B members agreed about the need of a petition to integrate feedback
of a lot of existing Delphi users.&lt;br /&gt;
Stay tuned!&lt;/p&gt;
&lt;/blockquote&gt;</description>
    
    
    
      </item>
    
  <item>
    <title>mORMots know how to swim like fishes</title>
    <link>http://blog.synopse.info/post/2013/04/24/mORMots-know-how-to-swim-like-fishes</link>
    <guid isPermaLink="false">urn:md5:2f9026dde1aca1fd6f9a4ede02a6b624</guid>
    <pubDate>Wed, 24 Apr 2013 15:53:00 +0200</pubDate>
    <dc:creator>A.Bouchez</dc:creator>
        <category>mORMot Framework</category>
        <category>AJAX</category><category>authentication</category><category>blog</category><category>Database</category><category>DataSnap</category><category>Delphi</category><category>HTTP</category><category>http.sys</category><category>JSON</category><category>mORMot</category><category>ORM</category><category>Rest</category><category>SQL</category><category>SQLite3</category>    
    <description>    &lt;p&gt;&lt;img src=&quot;http://www.alansmind.com/marmot.jpg&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;Another great video by &lt;a href=&quot;http://synopse.info/forum/profile.php?id=835&quot;&gt;warleyalex&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;This time, a full FishFacts demo in AJAX, using mORMot and its
&lt;em&gt;SQLite3&lt;/em&gt; ORM as server.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://youtu.be/eqzJQftv89s&quot;&gt;See it on YouTube&lt;/a&gt;!&lt;/p&gt;
&lt;p&gt;Feedback is &lt;a href=&quot;http://synopse.info/forum/viewtopic.php?id=1236&quot;&gt;welcome on our forum&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Update:&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;I've just uploaded the corresponding &lt;em&gt;source code&lt;/em&gt; to our
repository.&lt;br /&gt;
See sample &lt;a href=&quot;http://synopse.info/fossil/dir?name=SQLite3/Samples/19+-+AJAX+ExtJS+FishFacts&quot;&gt;
19 - AJAX ExtJS FishFacts&lt;/a&gt;.&lt;br /&gt;
You need to &lt;a href=&quot;http://blog.synopse.info/post/2013/04/24/You%20need%20to%20download%20the%20DB%20from%20http://synopse.info/files/samples/Project19Server.zip&quot;&gt;
download the corresponding DB file&lt;/a&gt; to run the sample.&lt;br /&gt;
Enjoy!&lt;/p&gt;</description>
    
    
    
      </item>
    
  <item>
    <title>TDataSet... now I'm confused</title>
    <link>http://blog.synopse.info/post/2013/04/22/TDataSet...-now-I-m-confused</link>
    <guid isPermaLink="false">urn:md5:1bc4e35a906d939003ac3a94190d2076</guid>
    <pubDate>Mon, 22 Apr 2013 07:34:00 +0200</pubDate>
    <dc:creator>A.Bouchez</dc:creator>
        <category>Pascal Programing</category>
        <category>blog</category><category>Database</category><category>Delphi</category><category>RAD</category><category>TDataSet</category><category>Unicode</category><category>UserInterface</category>    
    <description>&lt;p&gt;You perhaps know that I'm not a big fan of the &lt;code&gt;TDataSet&lt;/code&gt; /
RAD DB approach for end-user applications.&lt;br /&gt;
They are easy to define, almost no code to write, and you are able to publish a
working solution very fast.&lt;/p&gt;
&lt;p&gt;But it is a nightmare to debug and maintain. I prefer the new
&lt;em&gt;DataBinding&lt;/em&gt; feature, or... of course... ORM!&lt;br /&gt;
In &lt;em&gt;mORMot&lt;/em&gt;, we have some auto-generated screens, and in our roadmap, we
forcast to use some auto-binding features, using a KISS by-convention MVC
pattern.&lt;/p&gt;
&lt;p&gt;For some users, we made a ORM / &lt;code&gt;TDataSet&lt;/code&gt; conversion unit.&lt;br /&gt;
And we discovered that &lt;code&gt;TDataSet&lt;/code&gt; has a weird, and very
misleading definition of its &lt;code&gt;AsString&lt;/code&gt; property, for Unicode
versions of Delphi.&lt;/p&gt;    &lt;p&gt;In the Delphi 2009+ implementation, you have to use &lt;code&gt;AsString&lt;/code&gt;
property for &lt;code&gt;AnsiString&lt;/code&gt; and &lt;code&gt;AsWideString&lt;/code&gt; for
&lt;code&gt;string=UnicodeString&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;In fact, the &lt;code&gt;As*String&lt;/code&gt; properties are defined as such:&lt;/p&gt;
&lt;pre&gt;
&lt;code&gt;property AsString: string read GetAsString write SetAsString;
property AsWideString: UnicodeString read GetAsWideString write SetAsWideString;
property AsAnsiString: AnsiString read GetAsAnsiString write SetAsAnsiString;
&lt;/code&gt;
&lt;/pre&gt;
&lt;p&gt;How on earth &lt;a href=&quot;http://stackoverflow.com/q/9459186/458259&quot;&gt;may we be
able to find out&lt;/a&gt; that &lt;code&gt;AsString: string &lt;/code&gt;returns in fact an
&lt;code&gt;AnsiString&lt;/code&gt;?&lt;br /&gt;
It just does not make sense at all, when compared to the rest of the
VCL/RTL.&lt;/p&gt;
&lt;p&gt;The implementation, which uses &lt;code&gt;TStringField&lt;/code&gt; class for
&lt;code&gt;AnsiString&lt;/code&gt; and &lt;code&gt;TWideStringField&lt;/code&gt; for
&lt;code&gt;string=UnicodeString&lt;/code&gt; just appear to be broken.&lt;/p&gt;
&lt;p&gt;Furthermore, &lt;a href=&quot;http://docwiki.embarcadero.com/Libraries/XE2/en/Data.DB.TField.AsString&quot;&gt;the
documentation is also broken&lt;/a&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Data.DB.TField.AsString&lt;br /&gt;
Represents the field's value as a string (Delphi) or an AnsiString
(C++).&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;This does not represent a &lt;code&gt;string&lt;/code&gt; in Delphi, but an
&lt;code&gt;AnsiString&lt;/code&gt;!&lt;br /&gt;
The fact that the property uses a plain &lt;code&gt;string=UnicodeString&lt;/code&gt; type
is perfectly misleading.&lt;/p&gt;
&lt;p&gt;From the database point of view, it is up to the DB driver to handle Unicode
or work with a specific charset.&lt;br /&gt;
But from the VCL point of view, in Delphi 2009+ you should only know about one
&lt;code&gt;string&lt;/code&gt; type, and be confident that using &lt;code&gt;AsString:
String&lt;/code&gt; will be Unicode-ready.&lt;/p&gt;
&lt;p&gt;If you use our &lt;code&gt;mORMotVCL.pas&lt;/code&gt; unit, &lt;a href=&quot;http://synopse.info/fossil/info/c6ef9c1d0f&quot;&gt;it will behave as
expected&lt;/a&gt;.&lt;br /&gt;
Thanks you &lt;a href=&quot;http://synopse.info/forum/profile.php?id=858&quot;&gt;sjerinic&lt;/a&gt;
for your input and patience about this issue!&lt;br /&gt;
Feedback &lt;a href=&quot;http://synopse.info/forum/viewtopic.php?pid=7452#p7452&quot;&gt;is
welcome&lt;/a&gt;!&lt;/p&gt;</description>
    
    
    
      </item>
    
  <item>
    <title>Two videos about EXTjs client of mORMot server</title>
    <link>http://blog.synopse.info/post/2013/04/02/Two-videos-about-EXTjs-client-of-mORMot-server</link>
    <guid isPermaLink="false">urn:md5:3fd39165aa02ec6c6a328673a57cdb6a</guid>
    <pubDate>Tue, 02 Apr 2013 20:35:00 +0200</pubDate>
    <dc:creator>A.Bouchez</dc:creator>
        <category>mORMot Framework</category>
        <category>AJAX</category><category>authentication</category><category>blog</category><category>Database</category><category>DataSnap</category><category>Delphi</category><category>HTTP</category><category>http.sys</category><category>JSON</category><category>mORMot</category><category>ORM</category><category>Rest</category><category>Source</category><category>SQL</category><category>SQLite3</category>    
    <description>    &lt;p&gt;Two nice videos, posted by a &lt;a href=&quot;http://synopse.info/forum/profile.php?id=835&quot;&gt;framework user&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The first one presents a &lt;a href=&quot;http://www.youtube.com/watch?v=e4vcglINrko&quot;&gt;remote RESTful access of a
&lt;em&gt;SQLite3&lt;/em&gt; database&lt;/a&gt;, hosted by a &lt;em&gt;mORMot&lt;/em&gt; server:&lt;/p&gt;
&lt;p&gt;&lt;iframe width=&quot;420&quot; height=&quot;315&quot; src=&quot;http://www.youtube.com/embed/e4vcglINrko&quot; frameborder=&quot;0&quot;&gt;&lt;/iframe&gt;&lt;/p&gt;
&lt;p&gt;After &lt;a href=&quot;http://synopse.info/forum/viewtopic.php?id=1182&quot;&gt;one post in
the forum&lt;/a&gt;, &lt;em&gt;warleyalex&lt;/em&gt; was able to easily &lt;a href=&quot;http://www.youtube.com/watch?v=fh1Iqt6-_uk&quot;&gt;add remote filtering of the
request&lt;/a&gt;:&lt;/p&gt;
&lt;p&gt;&lt;iframe width=&quot;420&quot; height=&quot;315&quot; src=&quot;http://www.youtube.com/embed/fh1Iqt6-_uk&quot; frameborder=&quot;0&quot;&gt;&lt;/iframe&gt;&lt;/p&gt;
&lt;p&gt;In addition to the &lt;a href=&quot;http://www.youtube.com/watch?v=LIl1HbjxnIA&quot;&gt;previous video&lt;/a&gt; about security
(by which the &lt;em&gt;mORMot&lt;/em&gt; authentication model seems much more secure than
&lt;em&gt;DataSnap&lt;/em&gt;'s), this is a very nice demo!&lt;br /&gt;
Thanks a lot, &lt;em&gt;warleyalex&lt;/em&gt; for the feedback and information!&lt;/p&gt;</description>
    
    
    
      </item>
    
  <item>
    <title>Adding some generic-based methods to mORMot</title>
    <link>http://blog.synopse.info/post/2013/03/28/Adding-some-generic-based-methods-to-mORMot</link>
    <guid isPermaLink="false">urn:md5:9888569fd6f816a63c0f3efe8c8390d3</guid>
    <pubDate>Thu, 28 Mar 2013 16:51:00 +0100</pubDate>
    <dc:creator>A.Bouchez</dc:creator>
        <category>mORMot Framework</category>
        <category>blog</category><category>Delphi</category><category>generics</category><category>mORMot</category><category>ORM</category><category>Source</category>    
    <description>    &lt;p&gt;We &lt;a href=&quot;http://synopse.info/fossil/info/0549ba7168&quot;&gt;have just added&lt;/a&gt;
a &lt;code&gt;TSQLTable.ToObjectList&amp;lt;T: class&amp;gt;()&lt;/code&gt; method.&lt;/p&gt;
&lt;p&gt;I want to add some generics-based methods to &lt;em&gt;mORMot&lt;/em&gt;, for newer
versions of Delphi.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;http://synopse.info/fossil/raw?name=63182c58a095edbcdbae824e797ba679217ca2c7&amp;amp;m=image/png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;What do you think of it?&lt;br /&gt;
Have you some method prototypes to propose?&lt;/p&gt;
&lt;p&gt;My first concern is that &lt;em&gt;FreePascal&lt;/em&gt; &lt;a href=&quot;http://wiki.freepascal.org/Generics&quot;&gt;does not offer the same syntax&lt;/a&gt;.&lt;br /&gt;
I suppose some &lt;code&gt;$ifdef...&lt;/code&gt; will be necessary here.. &lt;img src=&quot;/themes/default/smilies/sad.png&quot; alt=&quot;:(&quot; class=&quot;smiley&quot; /&gt;&lt;/p&gt;
&lt;p&gt;Feel free to &lt;a href=&quot;http://synopse.info/forum/viewtopic.php?id=1188&quot;&gt;post
your proposal to the forum&lt;/a&gt;.&lt;/p&gt;</description>
    
    
    
      </item>
    
  <item>
    <title>Introducing TSQLTable.Step() method</title>
    <link>http://blog.synopse.info/post/2013/03/27/Introducing-TSQLTable.Step%28%29-method</link>
    <guid isPermaLink="false">urn:md5:559c58efb7887040326d647e2595369a</guid>
    <pubDate>Wed, 27 Mar 2013 17:26:00 +0100</pubDate>
    <dc:creator>A.Bouchez</dc:creator>
        <category>mORMot Framework</category>
        <category>blog</category><category>Database</category><category>Delphi</category><category>mORMot</category><category>ORM</category><category>Source</category><category>SQL</category><category>SQLite3</category>    
    <description>&lt;p&gt;We have just added &lt;code&gt;TSQLTable.Step(), FieldBuffer()&lt;/code&gt; and
&lt;code&gt;Field()&lt;/code&gt; methods, handling a cursor at &lt;code&gt;TSQLTable&lt;/code&gt;
level, with optional late-binding column access.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;http://synopse.info/fossil/raw/SQLite3/Documentation/cartoon03.png?name=141722b8808e8b35fb39a2137e4c6a46ba09431a&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;It allows to retrieve results from a &lt;code&gt;TSQLTable&lt;/code&gt; /
&lt;code&gt;TSQLTableJSON&lt;/code&gt; result sets within a &amp;quot;cursor-like&amp;quot;
orientation.&lt;br /&gt;
That is, no need to specify the row number, but write a simple while
&lt;code&gt;aList.Step do ...&lt;/code&gt; loop.&lt;/p&gt;
&lt;p&gt;Of course, you should better use &lt;code&gt;TSQLRecord.FillPrepare&lt;/code&gt; most of
the time, and access the data from a &lt;code&gt;TSQLRecord&lt;/code&gt; instance.&lt;br /&gt;
But it can be very useful, e.g. when working on a custom JOINed SQL
statement.&lt;/p&gt;    &lt;p&gt;&lt;code&gt;TSQLTableJSON&lt;/code&gt; will expect some &lt;em&gt;JSON&lt;/em&gt; content as input,
will parse it in rows and columns, associate it with one or more optional
&lt;code&gt;TSQLRecord&lt;/code&gt; class types, then will let you access the data via its
&lt;code&gt;Get*&lt;/code&gt; methods.&lt;/p&gt;
&lt;p&gt;You can use this &lt;code&gt;TSQLTableJSON&lt;/code&gt; class as in the following
example:&lt;/p&gt;
&lt;pre&gt;
&lt;strong&gt;procedure&lt;/strong&gt; WriteBabiesStartingWith(&lt;strong&gt;const&lt;/strong&gt; Letters: RawUTF8; Sex: TSex);
&lt;strong&gt;var&lt;/strong&gt; aList: TSQLTableJSON;
    Row: integer;
&lt;strong&gt;begin&lt;/strong&gt;
  &lt;span style=&quot;background-color:yellow;&quot;&gt;aList := Client.MultiFieldValues(TSQLBaby,'ID,BirthDate',&lt;/span&gt;
    &lt;span style=&quot;background-color:yellow;&quot;&gt;'Name LIKE ? AND Sex = ?',[Letters+'%',ord(Sex)]);&lt;/span&gt;
  &lt;strong&gt;if&lt;/strong&gt; aList=&lt;strong&gt;nil then&lt;/strong&gt;
    &lt;strong&gt;raise&lt;/strong&gt; Exception.Create('Impossible to retrieve data from Server');
  &lt;strong&gt;try&lt;/strong&gt;
    &lt;strong&gt;for&lt;/strong&gt; Row := 1 &lt;strong&gt;to&lt;/strong&gt; aList.RowCount &lt;strong&gt;do&lt;/strong&gt;
      writeln('ID=',aList.GetAsInteger(Row,0),' BirthDate=',aList.Get(Row,1));
  &lt;strong&gt;finally&lt;/strong&gt;
    aList.Free;
  &lt;strong&gt;end&lt;/strong&gt;;
&lt;strong&gt;end&lt;/strong&gt;;
&lt;/pre&gt;
&lt;p&gt;For a record with a huge number of fields, specifying the needed fields
could save some bandwidth. In the above sample code, the &lt;code&gt;ID&lt;/code&gt; column
has a field index of 0 (so is retrieved via
&lt;code&gt;aList.GetAsInteger(Row,0)&lt;/code&gt;) and the &lt;code&gt;BirthDate&lt;/code&gt; column
has a field index of 1 (so is retrieved as a &lt;code&gt;PUTF8Char&lt;/code&gt; via
&lt;code&gt;aList.Get(Row,1)&lt;/code&gt;). All data rows are processed via a loop using
the &lt;code&gt;RowCount&lt;/code&gt; property count - first data row is indexed as 1,
since the row 0 will contain the column names.&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;TSQLTable&lt;/code&gt; class has some methods dedicated to direct cursor
handling, as such:&lt;/p&gt;
&lt;pre&gt;
&lt;strong&gt;procedure&lt;/strong&gt; WriteBabiesStartingWith(&lt;strong&gt;const&lt;/strong&gt; Letters: RawUTF8; Sex: TSex);
&lt;strong&gt;var&lt;/strong&gt; aList: TSQLTableJSON;
&lt;strong&gt;begin&lt;/strong&gt;
  aList := Client.MultiFieldValues(TSQLBaby,'ID,BirthDate',
    'Name LIKE ? AND Sex = ?',[Letters+'%',ord(Sex)]);
  &lt;strong&gt;try&lt;/strong&gt;
    &lt;span style=&quot;background-color:yellow;&quot;&gt;&lt;strong&gt;while&lt;/strong&gt; aList.Step &lt;strong&gt;do&lt;/strong&gt;&lt;/span&gt;
      &lt;span style=&quot;background-color:yellow;&quot;&gt;writeln('ID=',aList.Field(0),' BirthDate=',aList.Field(1));&lt;/span&gt;
  &lt;strong&gt;finally&lt;/strong&gt;
    aList.Free;
  &lt;strong&gt;end&lt;/strong&gt;;
&lt;strong&gt;end&lt;/strong&gt;;
&lt;/pre&gt;
&lt;p&gt;By using the &lt;code&gt;TSQLTable.Step&lt;/code&gt; method, you do not need to check
that &lt;code&gt;aList&amp;lt;&amp;gt;nil&lt;/code&gt;, since it will return false if
&lt;code&gt;aList&lt;/code&gt; is not assigned. And you do not need to access the
&lt;code&gt;RowCount&lt;/code&gt; property, nor specify the current row number.&lt;/p&gt;
&lt;p&gt;We may have used not the field index, but the field name, within the
loop:&lt;/p&gt;
&lt;pre&gt;
      writeln('ID=',aList.Field('ID'),' BirthDate=',aList.Field('BirthDate'));
&lt;/pre&gt;
&lt;p&gt;You can also access the field values using late-binding and a local variant,
which gives some perfectly readable code:&lt;/p&gt;
&lt;pre&gt;
&lt;strong&gt;procedure&lt;/strong&gt; WriteBabiesStartingWith(&lt;strong&gt;const&lt;/strong&gt; Letters: RawUTF8; Sex: TSex);
&lt;strong&gt;var&lt;/strong&gt; baby: &lt;strong&gt;variant&lt;/strong&gt;;
&lt;strong&gt;begin&lt;/strong&gt;
  &lt;strong&gt;with&lt;/strong&gt; Client.MultiFieldValues(TSQLBaby,'ID,BirthDate'
    'Name LIKE ? AND Sex = ?',[Letters+'%',ord(Sex)]) &lt;strong&gt;do&lt;/strong&gt;
  &lt;strong&gt;try&lt;/strong&gt;
    &lt;span style=&quot;background-color:yellow;&quot;&gt;&lt;strong&gt;while&lt;/strong&gt; Step(false,@baby) &lt;strong&gt;do&lt;/strong&gt;&lt;/span&gt;
      &lt;span style=&quot;background-color:yellow;&quot;&gt;writeln('ID=',baby.ID,' BirthDate=',baby.BirthDate);&lt;/span&gt;
  &lt;strong&gt;finally&lt;/strong&gt;
    Free;
  &lt;strong&gt;end&lt;/strong&gt;;
&lt;strong&gt;end&lt;/strong&gt;;
&lt;/pre&gt;
&lt;p&gt;In the above code, late-binding will search for the &lt;code&gt;&amp;quot;ID&amp;quot;&lt;/code&gt; and
&lt;code&gt;&amp;quot;BirthDate&amp;quot;&lt;/code&gt; fields at runtime. But the ability to write
&lt;code&gt;baby.ID&lt;/code&gt; and &lt;code&gt;baby.BirthDate&lt;/code&gt; is very readable. Using a
&lt;code&gt;with ... do&lt;/code&gt; statement makes the code shorter, but should be
avoided if it leads into confusion, e.g. in case of more complex process within
the loop.&lt;/p&gt;
&lt;p&gt;See also the following methods of &lt;code&gt;TSQLRest&lt;/code&gt;:
&lt;code&gt;OneFieldValue&lt;/code&gt;, &lt;code&gt;OneFieldValues&lt;/code&gt;,
&lt;code&gt;MultiFieldValue&lt;/code&gt;, &lt;code&gt;MultiFieldValues&lt;/code&gt; which are able to
retrieve either a &lt;code&gt;TSQLTableJSON&lt;/code&gt;, or a &lt;em&gt;dynamic array&lt;/em&gt; of
&lt;code&gt;integer&lt;/code&gt; or &lt;code&gt;RawUTF8&lt;/code&gt;. And also &lt;code&gt;List&lt;/code&gt; and
&lt;code&gt;ListFmt&lt;/code&gt; methods of &lt;code&gt;TSQLRestClient&lt;/code&gt;, if you want to
make a &lt;code&gt;JOIN&lt;/code&gt; against multiple tables at once.&lt;/p&gt;
&lt;p&gt;Feedback is &lt;a href=&quot;http://synopse.info/forum/viewtopic.php?id=1185&quot;&gt;welcome in our forum&lt;/a&gt;, as
usual.&lt;/p&gt;</description>
    
    
    
      </item>
    
  <item>
    <title>Delphi is just a perfect fit for the average programmer</title>
    <link>http://blog.synopse.info/post/2013/03/26/Delphi-is-just-a-perfect-fit-for-the-average-programmer</link>
    <guid isPermaLink="false">urn:md5:d3bca4d0592ecf7c56e6e06f28c0e1d5</guid>
    <pubDate>Tue, 26 Mar 2013 20:20:00 +0100</pubDate>
    <dc:creator>A.Bouchez</dc:creator>
        <category>Pascal Programing</category>
        <category>blog</category><category>C</category><category>Delphi</category><category>GoodPractice</category><category>Java</category><category>performance</category>    
    <description>&lt;p&gt;On the &lt;a href=&quot;https://forums.embarcadero.com/message.jspa?messageID=546293#546293&quot;&gt;Embarcadero
forums&lt;/a&gt;, some user did have a perfectly sane reaction, about a non obvious
integer type cast like &lt;code&gt;Int64Var := Int32Var*Int32Var&lt;/code&gt;, which may
overflow.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;We've got to stop becoming, as one poster put it, &amp;quot;human pre-compilers&amp;quot;
for Delphi.&lt;br /&gt;
The compiler ought to have the common sense to not need the programmer to cast
the two integer values.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;I respectfully think just the opposite.&lt;br /&gt;
&lt;img src=&quot;/themes/default/smilies/wink.png&quot; alt=&quot;;)&quot; class=&quot;smiley&quot; /&gt;&lt;/p&gt;
&lt;p&gt;Such a type cast is part of the language grammar.&lt;br /&gt;
If you know the grammar, you will know how it will be compiled.&lt;/p&gt;
&lt;p&gt;To be honest, you have the same in all languages, with more or less range
checking, optimization, and implicit conversion.&lt;br /&gt;
This is why I like Delphi: it can be mastered by any programmers, whereas truly
mastering Java or .Net needs a genius.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;http://blog.synopse.info/public/mORMot/IamLost.png&quot; alt=&quot;&quot; title=&quot;I am lost, mar. 2013&quot; /&gt;&lt;br /&gt;
Delphi is just... human...&lt;/p&gt;    &lt;p&gt;This is exactly what I like so much with Delphi, just as with C or
C++.&lt;br /&gt;
I like to know which asm code will be generated.&lt;br /&gt;
I like to know how memory is allocated/released.&lt;br /&gt;
I do not like to play with a black box, but I enjoy to rely on identified
source code (e.g. the Delphi RTL).&lt;br /&gt;
I like to know how the hardware will react to my code.&lt;br /&gt;
I like to run a profiler and see what is going on here.&lt;br /&gt;
I like to know how my software will run on the customer network and
database.&lt;/p&gt;
&lt;p&gt;When you know how the language and the compiler works, when you know about
the various data structures used and generated by the compiler and the RTL, you
are more efficient with it.&lt;br /&gt;
Compilers are just tools.&lt;br /&gt;
Computer languages are just abstraction of the hardware.&lt;/p&gt;
&lt;p&gt;Even with more &amp;quot;high level&amp;quot; languages like JavaScript, you have to &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/JavaScript/Typed_arrays&quot;&gt;use some
dedicated structures&lt;/a&gt;, and be aware of the potential of the JIT compiler, if
you want the process to be as efficient as possible.&lt;/p&gt;
&lt;p&gt;One of the problems of today's programmers is that most of them do not know
any more what is &amp;quot;under the hood&amp;quot;.&lt;br /&gt;
Coding is seen as a list of recipes.&lt;br /&gt;
It is pretty easy to (ab)use of Intellisense/Resharper, Linq, and whatever the
language/IDE is offering to you, and you forget about what will be
executed.&lt;br /&gt;
Everything is fine on your own computer, but on the customer's side, it does
not work as expected.&lt;br /&gt;
It just remembers me coding in &lt;a href=&quot;http://en.wikipedia.org/wiki/ZX81&quot;&gt;ZX81
basic&lt;/a&gt;... already typing on a black box... good old days doing plenty of
things with 768 bytes of free RAM... &lt;/p&gt;
&lt;p&gt;You can be a lazy programmer (which is something good, IMHO), and at the
same time know what happens.&lt;br /&gt;
In fact, a true lazy programmer needs to know how it works.&lt;/p&gt;
&lt;p&gt;Delphi is simple enough to be understood by an average human being like me
(after years of daily efforts), whereas I consider mastering .Net or Java
frameworks is &lt;a href=&quot;http://www.tomshardware.com/news/Linux-Linus-Torvalds-kernel-too-complex-code,14495.html&quot;&gt;
out of scope&lt;/a&gt; of my poor brain.&lt;br /&gt;
Object pascal is a abstract enough to allow high-level style of coding (e.g. as
I've done with &lt;em&gt;&lt;a href=&quot;http://blog.synopse.info/post/2013/03/25/SynProject-tool-1.18&quot;&gt;SynProject&lt;/a&gt;&lt;/em&gt;), and also
low-level enough to &lt;a href=&quot;http://blog.synopse.info/post/2012/11/23/Speed-comparison-between-WCF%2C-Java%2C-DataSnap-and-mORMot&quot;&gt;release
the whole hardware potential&lt;/a&gt;.&lt;/p&gt;</description>
    
    
    
      </item>
    
  <item>
    <title>SynProject tool 1.18</title>
    <link>http://blog.synopse.info/post/2013/03/25/SynProject-tool-1.18</link>
    <guid isPermaLink="false">urn:md5:54a1952bdc17bd8587e1ddae4c8e5987</guid>
    <pubDate>Mon, 25 Mar 2013 22:58:00 +0100</pubDate>
    <dc:creator>A.Bouchez</dc:creator>
        <category>SynProject documentation and versioning</category>
        <category>blog</category><category>Delphi</category><category>Documentation</category><category>GoodPractice</category><category>mORMot</category><category>Source</category><category>Synopse</category><category>SynProject</category>    
    <description>    &lt;p&gt;We have uploaded an updatetd compiled version of our Open Source
&lt;em&gt;SynProject&lt;/em&gt; tool in &lt;a href=&quot;http://synopse.info/files/SynProject.zip&quot;&gt;SynProject.zip&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Synopse &lt;em&gt;SynProject&lt;/em&gt; is an open source application for code source
versioning and automated documentation of software projects.&lt;br /&gt;
Licensed under a GPL license.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;http://synopse.info/files/synproject/SynProject05.png&quot; width=&quot;479&quot; height=&quot;353&quot; /&gt;&lt;/p&gt;
&lt;p&gt;Main feature is a new (better-looking?) template for the generated
files.&lt;br /&gt;
See our &lt;a href=&quot;http://synopse.info/fossil/wiki?name=Downloads&quot;&gt;&lt;em&gt;mORMot&lt;/em&gt; framework
documentation&lt;/a&gt; for a good sample of rendering content.&lt;/p&gt;
&lt;p&gt;The &lt;a href=&quot;http://synopse.info/fossil/wiki?name=SynProject&quot;&gt;internal wiki
pages&lt;/a&gt; related to this tool has also been refreshed.&lt;/p&gt;
&lt;p&gt;Feedback is &lt;a href=&quot;http://synopse.info/forum/viewtopic.php?id=1180&quot;&gt;welcome on our forum&lt;/a&gt;!&lt;/p&gt;</description>
    
    
    
      </item>
    
  <item>
    <title>Download latest version of sqlite3.dll for Windows 64 bit</title>
    <link>http://blog.synopse.info/post/2013/03/23/Latest-version-of-sqlite3.dll-for-Windows-64-bit</link>
    <guid isPermaLink="false">urn:md5:f681cc9300acc5ce77c26ece4a46b2bf</guid>
    <pubDate>Sat, 23 Mar 2013 10:16:00 +0100</pubDate>
    <dc:creator>A.Bouchez</dc:creator>
        <category>mORMot Framework</category>
        <category>64bit</category><category>blog</category><category>C</category><category>mORMot</category><category>ORM</category><category>Source</category><category>SQLite3</category>    
    <description>    &lt;p&gt;Up to now, there is no official Win64 version of the &lt;em&gt;SQlite3&lt;/em&gt;
library released in &lt;a href=&quot;http://sqlite.org&quot;&gt;http://sqlite.org&lt;/a&gt;..&lt;br /&gt;
It is in fact very difficult to find a ready-to-use and
up-to-date &lt;code&gt;SQLite3-64.dll&lt;/code&gt; from Internet, for Win64.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;http://www.sqlite.org/images/sqlite370_banner.gif&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;You can find our own 3.7.16 version of the &lt;em&gt;SQlite3&lt;/em&gt; external
library, to be used in 64 bit mode, to be downloaded from &lt;a href=&quot;http://synopse.info/files/SQLite3-64.7z&quot;&gt;SQLite3-64.7z&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;It includes FTS3/FTS4 virtual tables, and was compiled in &lt;em&gt;release&lt;/em&gt;
mode.&lt;/p&gt;
&lt;p&gt;Compiled with &lt;a href=&quot;http://blogs.embarcadero.com/davidi/2013/01/25/42392&quot;&gt;the latest version of
Rad Studio XE3&lt;/a&gt;, which uses the LLVM 64 bit compiler as back-end.&lt;br /&gt;
Thanks to &lt;a href=&quot;http://synopse.info/forum/profile.php?id=702&quot;&gt;Hans&lt;/a&gt;
for compiling and sharing the binary!&lt;/p&gt;
&lt;p&gt;This is the version we use when our &lt;a href=&quot;http://blog.synopse.info/post/2013/03/07/64-bit-compatibility-of-mORMot-core-units&quot;&gt;&lt;em&gt;mORMot&lt;/em&gt;
framework targets Win64&lt;/a&gt;, using Delphi XE2/XE3.&lt;/p&gt;</description>
    
    
    
      </item>
    
  <item>
    <title>x64 optimized asm of FillChar() and Move() for Win64</title>
    <link>http://blog.synopse.info/post/2013/03/13/x64-optimized-asm-of-FillChar%28%29-and-Move%28%29-for-Win64</link>
    <guid isPermaLink="false">urn:md5:d079d7873be490525a39c0c1f5c49b8a</guid>
    <pubDate>Wed, 13 Mar 2013 13:18:00 +0100</pubDate>
    <dc:creator>A.Bouchez</dc:creator>
        <category>Pascal Programing</category>
        <category>64bit</category><category>asm</category><category>blog</category><category>mORMot</category><category>performance</category><category>Source</category>    
    <description>    &lt;p&gt;We have included &lt;a href=&quot;http://synopse.info/fossil/fdiff?v1=6281d4cc1e890320&amp;amp;v2=f43d4dde9a8479d4&quot;&gt;x64
optimized asm of &lt;code&gt;FillChar()&lt;/code&gt; and &lt;code&gt;Move()&lt;/code&gt; for Win64&lt;/a&gt;
- for corresponding compiler targets, i.e. Delphi XE2 and XE3.&lt;br /&gt;
It will handle properly &lt;a href=&quot;http://en.wikipedia.org/wiki/Instruction_prefetch&quot;&gt;cache prefetch&lt;/a&gt; and
appropriate &lt;a href=&quot;http://en.wikipedia.org/wiki/Sse2&quot;&gt;SSE2 move
instructions&lt;/a&gt;. &lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;http://www.co-pylit.org/courses/COSC2425/_images/PentiumBlockDiagram.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;System.pas&lt;/code&gt; unit of Delphi RTL will be patched at startup,
unless the &lt;code&gt;NOX64PATCHRTL&lt;/code&gt; conditional is defined.&lt;br /&gt;
Therefore, whole application may benefit for this optimized version.&lt;/p&gt;
&lt;p&gt;Performance improvement is noticeable, when compared with the original
pascal-based version included in &lt;code&gt;System.pas&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;By the way, the Delphi &lt;em&gt;x64&lt;/em&gt; built-in assembler does not recognize
the &lt;code&gt;movnti&lt;/code&gt; opcode... so we had to inline it as plain
&lt;code&gt;db&lt;/code&gt; hexadecimal values.&lt;br /&gt;
A bit disappointing. Until now, we did not suffer from anything in regard to
the &lt;em&gt;x64&lt;/em&gt; compatibility at Delphi level.&lt;/p&gt;
&lt;p&gt;No stand-alone unit available yet, since it is included in our
&lt;code&gt;SynCommons.pas&lt;/code&gt; shared unit, starting with the 1.18 revision of
&lt;em&gt;mORMot&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Feedback is &lt;a href=&quot;http://synopse.info/forum/viewtopic.php?id=1161&quot;&gt;welcome, as usual&lt;/a&gt;!&lt;/p&gt;</description>
    
    
    
      </item>
    
  <item>
    <title>64 bit compatibility of mORMot units</title>
    <link>http://blog.synopse.info/post/2013/03/07/64-bit-compatibility-of-mORMot-core-units</link>
    <guid isPermaLink="false">urn:md5:6e596c195a5b4c727b6ad5bfe2c840dc</guid>
    <pubDate>Thu, 07 Mar 2013 17:19:00 +0100</pubDate>
    <dc:creator>A.Bouchez</dc:creator>
        <category>mORMot Framework</category>
        <category>64bit</category><category>asm</category><category>blog</category><category>Database</category><category>Delphi</category><category>factory</category><category>http.sys</category><category>i18n</category><category>interface</category><category>JSON</category><category>MetaData</category><category>mock</category><category>mORMot</category><category>object</category><category>ORM</category><category>Parsing</category><category>PDF</category><category>Rest</category><category>RTTI</category><category>session</category><category>SOA</category><category>Source</category><category>SQL</category><category>SQLite3</category><category>stub</category><category>SynDB</category><category>TaskDialog</category><category>Testing</category><category>Unicode</category><category>UserInterface</category><category>VirtualTable</category><category>WCF</category><category>weak pointers</category>    
    <description>&lt;p&gt;I'm happy to announce that &lt;em&gt;mORMot&lt;/em&gt; units are now &lt;a href=&quot;http://synopse.info/fossil/info/fb893df6fe&quot;&gt;compiling and working great in 64
bit mode&lt;/a&gt;, under Windows.&lt;br /&gt;
Need a Delphi XE2/XE3 compiler, of course!&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;http://3.bp.blogspot.com/_FUNuXxCxZA8/SqFBDD93GVI/AAAAAAAABIs/-M7J7YivsPM/s400/Marmot.JPG&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;ORM and services are now available in &lt;em&gt;Win64&lt;/em&gt;, on both client and
server sides.&lt;br /&gt;
Low-level &lt;em&gt;x64&lt;/em&gt; assembler stubs have been created, tested and
optimized.&lt;br /&gt;
UI part is also available... that is grid display, reporting (with &lt;em&gt;pdf&lt;/em&gt;
export and display anti-aliasing), ribbon auto-generation,
&lt;code&gt;SynTaskDialog&lt;/code&gt;, i18n... the main &lt;em&gt;SynFile&lt;/em&gt; demo just works
great!&lt;/p&gt;
&lt;p&gt;Overall impression is very positive, and speed is comparable to 32 bit
version (only 10-15% slower).&lt;/p&gt;
&lt;p&gt;Speed decrease seems to be mostly due to doubled pointer size, and some less
optimized part of the official Delphi RTL.&lt;br /&gt;
But since &lt;em&gt;mORMot&lt;/em&gt; core uses its own set of functions (e.g. for
JSON serialization, RTTI support or interface calls or stubbing), we were able
to release the whole 64 bit power of your hardware.&lt;/p&gt;
&lt;p&gt;Delphi 64 bit compiler sounds stable and efficient. Even when working at low
level, with assembler stubs.&lt;br /&gt;
Generated code sounds more optimized than the one emitted by
&lt;em&gt;FreePascalCompiler&lt;/em&gt; - and RTL is very close to 32 bit mode.&lt;br /&gt;
Overall, VCL conversion worked as easily than a simple re-build.&lt;br /&gt;
Embarcadero's people did a great job for VCL &lt;em&gt;Win64&lt;/em&gt; support, here!&lt;/p&gt;    &lt;p&gt;&lt;em&gt;SQlite3&lt;/em&gt; works great in 64 bit mode.&lt;/p&gt;
&lt;p&gt;You can find our own 3.7.16 version of the &lt;em&gt;SQlite3&lt;/em&gt; external
library, to be used in 64 bit mode, from &lt;a href=&quot;http://synopse.info/files/SQLite3-64.7z&quot;&gt;SQLite3-64.7z&lt;/a&gt;, since there is no
official &lt;em&gt;Win64&lt;/em&gt; library released yet in &lt;a href=&quot;http://sqlite.org&quot;&gt;http://sqlite.org&lt;/a&gt;&lt;br /&gt;
No problem so far, and pretty good performance.&lt;br /&gt;
Jut a weird bug about &lt;code&gt;SQLITE_TRANSIENT&lt;/code&gt; constant, which should be
&lt;code&gt;pointer(integer(-1))&lt;/code&gt; instead of &lt;code&gt;pointer(-1)&lt;/code&gt; when
working with virtual tables columns - but nothing to care of in your user code,
since the framework will handle it for you.&lt;/p&gt;
&lt;p&gt;I suspect some part of official &lt;code&gt;System.RTTI.pas&lt;/code&gt; unit as
provided in XE2/XE3 is broken in &lt;em&gt;Win64&lt;/em&gt;.&lt;br /&gt;
For instance, I think it does not handle a method returning a string.&lt;br /&gt;
Our &lt;code&gt;mORMot.pas&lt;/code&gt; implementation has been tested with the same
regression code as in 32 bit mode.&lt;/p&gt;
&lt;p&gt;Your own tests and feedback are welcome!&lt;br /&gt;
Feedback and detailed tests results are &lt;a href=&quot;http://synopse.info/forum/viewtopic.php?id=1153&quot;&gt;available in our
forum&lt;/a&gt;!&lt;/p&gt;</description>
    
    
    
      </item>
    
  <item>
    <title>Using external MinGW/VisualC++ sqlite3.dll - including benchmark</title>
    <link>http://blog.synopse.info/post/2013/02/25/Using-external-MinGW/VisualC-sqlite3.dll-including-benchmark</link>
    <guid isPermaLink="false">urn:md5:41331b38fd7dde023505b9aa0e72c3f7</guid>
    <pubDate>Mon, 25 Feb 2013 23:18:00 +0100</pubDate>
    <dc:creator>A.Bouchez</dc:creator>
        <category>mORMot Framework</category>
        <category>64bit</category><category>blog</category><category>C</category><category>Database</category><category>Delphi</category><category>FTS3</category><category>FTS4</category><category>LateBinding</category><category>mORMot</category><category>performance</category><category>Source</category><category>SQL</category><category>SQLite3</category>    
    <description>&lt;p&gt;With upcoming revision 1.18 of the framework, our
&lt;code&gt;SynSQlite3.pas&lt;/code&gt; unit is able to access the &lt;em&gt;SQLite3&lt;/em&gt; engine
in two ways:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Either &lt;em&gt;statically linked&lt;/em&gt; within the project executable;&lt;/li&gt;
&lt;li&gt;Or from an external &lt;code&gt;sqlite3.dll&lt;/code&gt; library file.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img src=&quot;http://synopse.info/fossil/raw/SQLite3/Documentation/cartoon01.png?name=949098186c8a8ea38c3c63b951654df3b1c29c31&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;The &lt;em&gt;SQLite3&lt;/em&gt; APIs and constants are defined in
&lt;code&gt;SynSQlite3.pas&lt;/code&gt;, and accessible via a &lt;code&gt;TSQLite3Library&lt;/code&gt;
class definition. It defines a global &lt;code&gt;sqlite3&lt;/code&gt; variable as
such:&lt;/p&gt;
&lt;pre&gt;
&lt;strong&gt;var&lt;/strong&gt;
  sqlite3: TSQLite3Library;
&lt;/pre&gt;
&lt;p&gt;To use the &lt;code&gt;SQLite3&lt;/code&gt; engine, an instance of
&lt;code&gt;TSQLite3Library&lt;/code&gt; class shall be assigned to this global variable.
Then all &lt;em&gt;mORMot&lt;/em&gt;'s calls will be made through it, calling e.g.
&lt;code&gt;sqlite3.open()&lt;/code&gt; instead of &lt;code&gt;sqlite3_open()&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;There are two implementation classes:&lt;/p&gt;
&lt;table&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Class&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Unit&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Purpose&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;TSQLite3LibraryStatic&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;SynSQLite3Static.pas&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Statically linked engine (&lt;code&gt;.obj&lt;/code&gt; within the
&lt;code&gt;.exe&lt;/code&gt;)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;TSQLite3LibraryDynamic&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;SynSQLite3.pas&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Instantiate an external &lt;code&gt;sqlite3.dll&lt;/code&gt; instance&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Referring to &lt;code&gt;SynSQLite3Static.pas&lt;/code&gt; in the &lt;code&gt;uses&lt;/code&gt;
clause of your project is enough to link the &lt;code&gt;.obj&lt;/code&gt; engine into your
executable.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Warning - breaking change&lt;/em&gt;: before version 1.18 of the framework,
link of static &lt;code&gt;.obj&lt;/code&gt; was forced - so you must add a reference to
&lt;code&gt;SynSQLite3Static&lt;/code&gt; in your project &lt;code&gt;uses&lt;/code&gt; clause to work
as expected.&lt;/p&gt;
&lt;p&gt;In order to use an external &lt;code&gt;sqlite3.dll&lt;/code&gt; library, you have to
set the global &lt;code&gt;sqlite3&lt;/code&gt; variable as such:&lt;/p&gt;
&lt;pre&gt;
 FreeAndNil(sqlite3); &lt;em&gt;// release any previous instance (e.g. static)&lt;/em&gt;
 &lt;span style=&quot;background-color:yellow;&quot;&gt;sqlite3 := TSQLite3LibraryDynamic.Create;&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;Of course, &lt;code&gt;FreeAndNil(sqlite3)&lt;/code&gt; is not mandatory, and should be
necessary only to avoid any memory leak if another &lt;em&gt;SQLite3&lt;/em&gt; engine
instance was allocated (may be the case if &lt;code&gt;SynSQLite3Static&lt;/code&gt; is
referred somewhere in your project's units).&lt;/p&gt;
&lt;p&gt;Here are some benchmarks, compiled with &lt;em&gt;Delphi XE3&lt;/em&gt;, run in a 32 bit
project, using either the static bcc-compiled engine, or an external
&lt;code&gt;sqlite3.dll&lt;/code&gt;, compiled via &lt;a href=&quot;https://www.google.com/url?sa=t&amp;amp;rct=j&amp;amp;q=&amp;amp;esrc=s&amp;amp;source=web&amp;amp;cd=1&amp;amp;cad=rja&amp;amp;ved=0CDUQFjAA&amp;amp;url=http%3A%2F%2Fwww.mingw.org%2F&amp;amp;ei=0oYsUeWiG8TVswatqYGwCQ&amp;amp;usg=AFQjCNEvRga3K2wHNky3Nsi91j4KZaJjEA&amp;amp;sig2=kk0qi5OslvSyHWjWl7eWpA&amp;amp;bvm=bv.42965579,d.Yms&quot;&gt;
MinGW&lt;/a&gt; or &lt;em&gt;Microsoft&lt;/em&gt; &lt;a href=&quot;http://msdn.microsoft.com/en-us/vstudio&quot;&gt;Visual C++&lt;/a&gt;.&lt;/p&gt;    &lt;p&gt;&lt;strong&gt;Static bcc-compiled .obj&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;First of all, our version included with &lt;code&gt;SynSQLite3Static.pas&lt;/code&gt;
unit, is to be benchmarked.&lt;/p&gt;
&lt;p&gt;&lt;br /&gt;
&lt;em&gt;Writing speed&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;http://chart.apis.google.com/chart?chtt=Insertion+speed+%28rows%2Fsecond%29&amp;amp;chxl=1:|Batch+Trans|Trans|Batch|Direct&amp;amp;chxt=x,y&amp;amp;chbh=a&amp;amp;chs=600x400&amp;amp;cht=bhg&amp;amp;chco=3D7930,3D8930,309F30,6070F0,5070E0,40C355,65D055,80C1A2,3D7930,3D8930,F05050,F04050,F04040,F01040,F0A280&amp;amp;chxr=0,0,575837&amp;amp;chds=0,575837,0,575837,0,575837,0,575837,0,575837&amp;amp;chd=t:477,389,97633,122865|868,869,96827,125862|84642,108624,104947,135105|338478,575373,337336,572147|338180,554446,331873,575837|486,496,101419,7011|799,303,105402,135109|93893,129550,109027,152811&amp;amp;chdl=SQLite3+%28file+full%29|SQLite3+%28file+off%29|SQLite3+%28mem%29|TObjectList+%28static%29|TObjectList+%28virtual%29|SQLite3+%28ext+full%29|SQLite3+%28ext+off%29|SQLite3+%28ext+mem%29&quot; /&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;http://chart.apis.google.com/chart?chtt=Insertion+speed+%28rows%2Fsecond%29&amp;amp;chxl=1:|SQLite3+%28ext+mem%29|SQLite3+%28ext+off%29|SQLite3+%28ext+full%29|TObjectList+%28virtual%29|TObjectList+%28static%29|SQLite3+%28mem%29|SQLite3+%28file+off%29|SQLite3+%28file+full%29&amp;amp;chxt=x,y&amp;amp;chbh=a&amp;amp;chs=600x400&amp;amp;cht=bhg&amp;amp;chco=3D7930,3D8930,309F30,6070F0,5070E0,40C355,65D055,80C1A2,3D7930,3D8930,F05050,F04050,F04040,F01040,F0A280&amp;amp;chxr=0,0,575837&amp;amp;chds=0,575837,0,575837,0,575837,0,575837,0,575837,0,575837,0,575837,0,575837&amp;amp;chd=t:477,868,84642,338478,338180,486,799,93893|389,869,108624,575373,554446,496,303,129550|97633,96827,104947,337336,331873,101419,105402,109027|122865,125862,135105,572147,575837,7011,135109,152811&amp;amp;chdl=Direct|Batch|Trans|Batch+Trans&quot; /&gt;&lt;/p&gt;
&lt;table&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt; &lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Direct&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Batch&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Trans&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Batch Trans&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;SQLite3 (file full)&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;477&lt;/td&gt;
&lt;td&gt;389&lt;/td&gt;
&lt;td&gt;97633&lt;/td&gt;
&lt;td&gt;122865&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;SQLite3 (file off)&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;868&lt;/td&gt;
&lt;td&gt;869&lt;/td&gt;
&lt;td&gt;96827&lt;/td&gt;
&lt;td&gt;125862&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;SQLite3 (mem)&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;84642&lt;/td&gt;
&lt;td&gt;108624&lt;/td&gt;
&lt;td&gt;104947&lt;/td&gt;
&lt;td&gt;135105&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;TObjectList (static)&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;338478&lt;/td&gt;
&lt;td&gt;575373&lt;/td&gt;
&lt;td&gt;337336&lt;/td&gt;
&lt;td&gt;572147&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;TObjectList (virtual)&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;338180&lt;/td&gt;
&lt;td&gt;554446&lt;/td&gt;
&lt;td&gt;331873&lt;/td&gt;
&lt;td&gt;575837&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;SQLite3 (ext full)&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;486&lt;/td&gt;
&lt;td&gt;496&lt;/td&gt;
&lt;td&gt;101419&lt;/td&gt;
&lt;td&gt;7011&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;SQLite3 (ext off)&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;799&lt;/td&gt;
&lt;td&gt;303&lt;/td&gt;
&lt;td&gt;105402&lt;/td&gt;
&lt;td&gt;135109&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;SQLite3 (ext mem)&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;93893&lt;/td&gt;
&lt;td&gt;129550&lt;/td&gt;
&lt;td&gt;109027&lt;/td&gt;
&lt;td&gt;152811&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;br /&gt;
&lt;em&gt;Reading speed&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;http://chart.apis.google.com/chart?chtt=Read+speed+%28rows%2Fsecond%29&amp;amp;chxl=1:|All+Direct|All+Virtual|By+one&amp;amp;chxt=x,y&amp;amp;chbh=a&amp;amp;chs=600x400&amp;amp;cht=bhg&amp;amp;chco=3D7930,3D8930,309F30,6070F0,5070E0,40C355,65D055,80C1A2,3D7930,3D8930,F05050,F04050,F04040,F01040,F0A280&amp;amp;chxr=0,0,910249&amp;amp;chds=0,910249,0,910249,0,910249&amp;amp;chd=t:26924,494559,500200|27750,496919,502714|124402,444404,495392|332778,907605,910249|331038,404891,905961|102707,261547,521322|131130,255806,513505|135784,248780,502664&amp;amp;chdl=SQLite3+%28file+full%29|SQLite3+%28file+off%29|SQLite3+%28mem%29|TObjectList+%28static%29|TObjectList+%28virtual%29|SQLite3+%28ext+full%29|SQLite3+%28ext+off%29|SQLite3+%28ext+mem%29&quot; /&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;http://chart.apis.google.com/chart?chtt=Read+speed+%28rows%2Fsecond%29&amp;amp;chxl=1:|SQLite3+%28ext+mem%29|SQLite3+%28ext+off%29|SQLite3+%28ext+full%29|TObjectList+%28virtual%29|TObjectList+%28static%29|SQLite3+%28mem%29|SQLite3+%28file+off%29|SQLite3+%28file+full%29&amp;amp;chxt=x,y&amp;amp;chbh=a&amp;amp;chs=600x400&amp;amp;cht=bhg&amp;amp;chco=3D7930,3D8930,309F30,6070F0,5070E0,40C355,65D055,80C1A2,3D7930,3D8930,F05050,F04050,F04040,F01040,F0A280&amp;amp;chxr=0,0,910249&amp;amp;chds=0,910249,0,910249,0,910249,0,910249,0,910249,0,910249,0,910249,0,910249&amp;amp;chd=t:26924,27750,124402,332778,331038,102707,131130,135784|494559,496919,444404,907605,404891,261547,255806,248780|500200,502714,495392,910249,905961,521322,513505,502664&amp;amp;chdl=By+one|All+Virtual|All+Direct&quot; /&gt;&lt;/p&gt;
&lt;table&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt; &lt;/td&gt;
&lt;td&gt;&lt;strong&gt;By one&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;All Virtual&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;All Direct&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;SQLite3 (file full)&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;26924&lt;/td&gt;
&lt;td&gt;494559&lt;/td&gt;
&lt;td&gt;500200&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;SQLite3 (file off)&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;27750&lt;/td&gt;
&lt;td&gt;496919&lt;/td&gt;
&lt;td&gt;502714&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;SQLite3 (mem)&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;124402&lt;/td&gt;
&lt;td&gt;444404&lt;/td&gt;
&lt;td&gt;495392&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;TObjectList (static)&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;332778&lt;/td&gt;
&lt;td&gt;907605&lt;/td&gt;
&lt;td&gt;910249&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;TObjectList (virtual)&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;331038&lt;/td&gt;
&lt;td&gt;404891&lt;/td&gt;
&lt;td&gt;905961&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;SQLite3 (ext full)&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;102707&lt;/td&gt;
&lt;td&gt;261547&lt;/td&gt;
&lt;td&gt;521322&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;SQLite3 (ext off)&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;131130&lt;/td&gt;
&lt;td&gt;255806&lt;/td&gt;
&lt;td&gt;513505&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;SQLite3 (ext mem)&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;135784&lt;/td&gt;
&lt;td&gt;248780&lt;/td&gt;
&lt;td&gt;502664&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Good old &lt;em&gt;Borland C++ builder&lt;/em&gt; produces some efficient code
here.&lt;br /&gt;
Those numbers are very good, when compared to the other two options.&lt;br /&gt;
Probably, using &lt;em&gt;FastMM4&lt;/em&gt; as memory manager and tuned compilation
options do make sense.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Official MinGW-compiled sqlite3.dll&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Here we used the official &lt;code&gt;sqlite3.dll&lt;/code&gt; library, as published in
the &lt;a href=&quot;http://sqlite.org&quot;&gt;http://sqlite.org&lt;/a&gt; web site, and compiled
with the MinGW/GCC compiler.&lt;/p&gt;
&lt;p&gt;&lt;br /&gt;
&lt;em&gt;Writing speed&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;http://chart.apis.google.com/chart?chtt=Insertion+speed+%28rows%2Fsecond%29&amp;amp;chxl=1:|Batch+Trans|Trans|Batch|Direct&amp;amp;chxt=x,y&amp;amp;chbh=a&amp;amp;chs=600x400&amp;amp;cht=bhg&amp;amp;chco=3D7930,3D8930,309F30,6070F0,5070E0,40C355,65D055,80C1A2,3D7930,3D8930,F05050,F04050,F04040,F01040,F0A280&amp;amp;chxr=0,0,573723&amp;amp;chds=0,573723,0,573723,0,573723,0,573723,0,573723&amp;amp;chd=t:418,503,86322,119420|918,873,93196,127317|83108,106951,99892,138003|320204,573723,324696,547465|323247,563697,324443,564716|501,410,100152,133679|913,438,102806,135545|96028,122798,108363,150920&amp;amp;chdl=SQLite3+%28file+full%29|SQLite3+%28file+off%29|SQLite3+%28mem%29|TObjectList+%28static%29|TObjectList+%28virtual%29|SQLite3+%28ext+full%29|SQLite3+%28ext+off%29|SQLite3+%28ext+mem%29&quot; /&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;http://chart.apis.google.com/chart?chtt=Insertion+speed+%28rows%2Fsecond%29&amp;amp;chxl=1:|SQLite3+%28ext+mem%29|SQLite3+%28ext+off%29|SQLite3+%28ext+full%29|TObjectList+%28virtual%29|TObjectList+%28static%29|SQLite3+%28mem%29|SQLite3+%28file+off%29|SQLite3+%28file+full%29&amp;amp;chxt=x,y&amp;amp;chbh=a&amp;amp;chs=600x400&amp;amp;cht=bhg&amp;amp;chco=3D7930,3D8930,309F30,6070F0,5070E0,40C355,65D055,80C1A2,3D7930,3D8930,F05050,F04050,F04040,F01040,F0A280&amp;amp;chxr=0,0,573723&amp;amp;chds=0,573723,0,573723,0,573723,0,573723,0,573723,0,573723,0,573723,0,573723&amp;amp;chd=t:418,918,83108,320204,323247,501,913,96028|503,873,106951,573723,563697,410,438,122798|86322,93196,99892,324696,324443,100152,102806,108363|119420,127317,138003,547465,564716,133679,135545,150920&amp;amp;chdl=Direct|Batch|Trans|Batch+Trans&quot; /&gt;&lt;/p&gt;
&lt;table&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt; &lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Direct&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Batch&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Trans&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Batch Trans&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;SQLite3 (file full)&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;418&lt;/td&gt;
&lt;td&gt;503&lt;/td&gt;
&lt;td&gt;86322&lt;/td&gt;
&lt;td&gt;119420&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;SQLite3 (file off)&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;918&lt;/td&gt;
&lt;td&gt;873&lt;/td&gt;
&lt;td&gt;93196&lt;/td&gt;
&lt;td&gt;127317&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;SQLite3 (mem)&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;83108&lt;/td&gt;
&lt;td&gt;106951&lt;/td&gt;
&lt;td&gt;99892&lt;/td&gt;
&lt;td&gt;138003&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;TObjectList (static)&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;320204&lt;/td&gt;
&lt;td&gt;573723&lt;/td&gt;
&lt;td&gt;324696&lt;/td&gt;
&lt;td&gt;547465&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;TObjectList (virtual)&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;323247&lt;/td&gt;
&lt;td&gt;563697&lt;/td&gt;
&lt;td&gt;324443&lt;/td&gt;
&lt;td&gt;564716&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;SQLite3 (ext full)&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;501&lt;/td&gt;
&lt;td&gt;410&lt;/td&gt;
&lt;td&gt;100152&lt;/td&gt;
&lt;td&gt;133679&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;SQLite3 (ext off)&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;913&lt;/td&gt;
&lt;td&gt;438&lt;/td&gt;
&lt;td&gt;102806&lt;/td&gt;
&lt;td&gt;135545&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;SQLite3 (ext mem)&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;96028&lt;/td&gt;
&lt;td&gt;122798&lt;/td&gt;
&lt;td&gt;108363&lt;/td&gt;
&lt;td&gt;150920&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;br /&gt;
&lt;em&gt;Reading speed&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;http://chart.apis.google.com/chart?chtt=Read+speed+%28rows%2Fsecond%29&amp;amp;chxl=1:|All+Direct|All+Virtual|By+one&amp;amp;chxt=x,y&amp;amp;chbh=a&amp;amp;chs=600x400&amp;amp;cht=bhg&amp;amp;chco=3D7930,3D8930,309F30,6070F0,5070E0,40C355,65D055,80C1A2,3D7930,3D8930,F05050,F04050,F04040,F01040,F0A280&amp;amp;chxr=0,0,905469&amp;amp;chds=0,905469,0,905469,0,905469&amp;amp;chd=t:26883,473529,438904|27729,472188,451304|116550,459432,457959|318248,891265,905469|327739,359040,892697|127346,180812,370288|127749,227759,438096|129792,224386,436338&amp;amp;chdl=SQLite3+%28file+full%29|SQLite3+%28file+off%29|SQLite3+%28mem%29|TObjectList+%28static%29|TObjectList+%28virtual%29|SQLite3+%28ext+full%29|SQLite3+%28ext+off%29|SQLite3+%28ext+mem%29&quot; /&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;http://chart.apis.google.com/chart?chtt=Read+speed+%28rows%2Fsecond%29&amp;amp;chxl=1:|SQLite3+%28ext+mem%29|SQLite3+%28ext+off%29|SQLite3+%28ext+full%29|TObjectList+%28virtual%29|TObjectList+%28static%29|SQLite3+%28mem%29|SQLite3+%28file+off%29|SQLite3+%28file+full%29&amp;amp;chxt=x,y&amp;amp;chbh=a&amp;amp;chs=600x400&amp;amp;cht=bhg&amp;amp;chco=3D7930,3D8930,309F30,6070F0,5070E0,40C355,65D055,80C1A2,3D7930,3D8930,F05050,F04050,F04040,F01040,F0A280&amp;amp;chxr=0,0,905469&amp;amp;chds=0,905469,0,905469,0,905469,0,905469,0,905469,0,905469,0,905469,0,905469&amp;amp;chd=t:26883,27729,116550,318248,327739,127346,127749,129792|473529,472188,459432,891265,359040,180812,227759,224386|438904,451304,457959,905469,892697,370288,438096,436338&amp;amp;chdl=By+one|All+Virtual|All+Direct&quot; /&gt;&lt;/p&gt;
&lt;table&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt; &lt;/td&gt;
&lt;td&gt;&lt;strong&gt;By one&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;All Virtual&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;All Direct&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;SQLite3 (file full)&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;26883&lt;/td&gt;
&lt;td&gt;473529&lt;/td&gt;
&lt;td&gt;438904&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;SQLite3 (file off)&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;27729&lt;/td&gt;
&lt;td&gt;472188&lt;/td&gt;
&lt;td&gt;451304&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;SQLite3 (mem)&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;116550&lt;/td&gt;
&lt;td&gt;459432&lt;/td&gt;
&lt;td&gt;457959&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;TObjectList (static)&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;318248&lt;/td&gt;
&lt;td&gt;891265&lt;/td&gt;
&lt;td&gt;905469&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;TObjectList (virtual)&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;327739&lt;/td&gt;
&lt;td&gt;359040&lt;/td&gt;
&lt;td&gt;892697&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;SQLite3 (ext full)&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;127346&lt;/td&gt;
&lt;td&gt;180812&lt;/td&gt;
&lt;td&gt;370288&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;SQLite3 (ext off)&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;127749&lt;/td&gt;
&lt;td&gt;227759&lt;/td&gt;
&lt;td&gt;438096&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;SQLite3 (ext mem)&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;129792&lt;/td&gt;
&lt;td&gt;224386&lt;/td&gt;
&lt;td&gt;436338&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;strong&gt;&lt;br /&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Visual C++ compiled sqlite3.dll&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;The &lt;em&gt;Open Source wxsqlite&lt;/em&gt; project provides a
&lt;code&gt;sqlite3.dll&lt;/code&gt; library, compiled with &lt;em&gt;Visual C++&lt;/em&gt;, and
including RC4 and AES 128/256 encryption (better than the basic encryption
implemented in &lt;code&gt;SynSQLite3Static.pas&lt;/code&gt;) - not available in the
official library.&lt;/p&gt;
&lt;p&gt;See &lt;a href=&quot;http://sourceforge.net/projects/wxcode/files/Components/wxSQLite3&quot;&gt;http://sourceforge.net/projects/wxcode/files/Components/wxSQLite3&lt;/a&gt;
to download the corresponding source code, and compiled &lt;code&gt;.dll&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&lt;br /&gt;
&lt;em&gt;Writing speed&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;http://chart.apis.google.com/chart?chtt=Insertion+speed+%28rows%2Fsecond%29&amp;amp;chxl=1:|Batch+Trans|Trans|Batch|Direct&amp;amp;chxt=x,y&amp;amp;chbh=a&amp;amp;chs=600x400&amp;amp;cht=bhg&amp;amp;chco=3D7930,3D8930,309F30,6070F0,5070E0,40C355,65D055,80C1A2,3D7930,3D8930,F05050,F04050,F04040,F01040,F0A280&amp;amp;chxr=0,0,596445&amp;amp;chds=0,596445,0,596445,0,596445,0,596445,0,596445&amp;amp;chd=t:470,498,93801,112170|886,819,90298,132883|86897,110287,105207,140896|332005,596445,321357,570776|327225,585000,329272,579240|459,503,91086,140599|501,519,110338,150394|98112,133276,117346,158634&amp;amp;chdl=SQLite3+%28file+full%29|SQLite3+%28file+off%29|SQLite3+%28mem%29|TObjectList+%28static%29|TObjectList+%28virtual%29|SQLite3+%28ext+full%29|SQLite3+%28ext+off%29|SQLite3+%28ext+mem%29&quot; /&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;http://chart.apis.google.com/chart?chtt=Insertion+speed+%28rows%2Fsecond%29&amp;amp;chxl=1:|SQLite3+%28ext+mem%29|SQLite3+%28ext+off%29|SQLite3+%28ext+full%29|TObjectList+%28virtual%29|TObjectList+%28static%29|SQLite3+%28mem%29|SQLite3+%28file+off%29|SQLite3+%28file+full%29&amp;amp;chxt=x,y&amp;amp;chbh=a&amp;amp;chs=600x400&amp;amp;cht=bhg&amp;amp;chco=3D7930,3D8930,309F30,6070F0,5070E0,40C355,65D055,80C1A2,3D7930,3D8930,F05050,F04050,F04040,F01040,F0A280&amp;amp;chxr=0,0,596445&amp;amp;chds=0,596445,0,596445,0,596445,0,596445,0,596445,0,596445,0,596445,0,596445&amp;amp;chd=t:470,886,86897,332005,327225,459,501,98112|498,819,110287,596445,585000,503,519,133276|93801,90298,105207,321357,329272,91086,110338,117346|112170,132883,140896,570776,579240,140599,150394,158634&amp;amp;chdl=Direct|Batch|Trans|Batch+Trans&quot; /&gt;&lt;/p&gt;
&lt;table&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt; &lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Direct&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Batch&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Trans&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Batch Trans&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;SQLite3 (file full)&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;470&lt;/td&gt;
&lt;td&gt;498&lt;/td&gt;
&lt;td&gt;93801&lt;/td&gt;
&lt;td&gt;112170&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;SQLite3 (file off)&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;886&lt;/td&gt;
&lt;td&gt;819&lt;/td&gt;
&lt;td&gt;90298&lt;/td&gt;
&lt;td&gt;132883&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;SQLite3 (mem)&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;86897&lt;/td&gt;
&lt;td&gt;110287&lt;/td&gt;
&lt;td&gt;105207&lt;/td&gt;
&lt;td&gt;140896&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;TObjectList (static)&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;332005&lt;/td&gt;
&lt;td&gt;596445&lt;/td&gt;
&lt;td&gt;321357&lt;/td&gt;
&lt;td&gt;570776&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;TObjectList (virtual)&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;327225&lt;/td&gt;
&lt;td&gt;585000&lt;/td&gt;
&lt;td&gt;329272&lt;/td&gt;
&lt;td&gt;579240&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;SQLite3 (ext full)&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;459&lt;/td&gt;
&lt;td&gt;503&lt;/td&gt;
&lt;td&gt;91086&lt;/td&gt;
&lt;td&gt;140599&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;SQLite3 (ext off)&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;501&lt;/td&gt;
&lt;td&gt;519&lt;/td&gt;
&lt;td&gt;110338&lt;/td&gt;
&lt;td&gt;150394&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;SQLite3 (ext mem)&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;98112&lt;/td&gt;
&lt;td&gt;133276&lt;/td&gt;
&lt;td&gt;117346&lt;/td&gt;
&lt;td&gt;158634&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;br /&gt;
&lt;em&gt;Reading speed&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;http://chart.apis.google.com/chart?chtt=Read+speed+%28rows%2Fsecond%29&amp;amp;chxl=1:|All+Direct|All+Virtual|By+one&amp;amp;chxt=x,y&amp;amp;chbh=a&amp;amp;chs=600x400&amp;amp;cht=bhg&amp;amp;chco=3D7930,3D8930,309F30,6070F0,5070E0,40C355,65D055,80C1A2,3D7930,3D8930,F05050,F04050,F04040,F01040,F0A280&amp;amp;chxr=0,0,885269&amp;amp;chds=0,885269,0,885269,0,885269&amp;amp;chd=t:28527,516689,521159|28927,513769,519156|127740,529100,523176|335053,869262,879352|334739,410374,885269|132594,258371,506277|138159,260892,507717|139567,254919,516208&amp;amp;chdl=SQLite3+%28file+full%29|SQLite3+%28file+off%29|SQLite3+%28mem%29|TObjectList+%28static%29|TObjectList+%28virtual%29|SQLite3+%28ext+full%29|SQLite3+%28ext+off%29|SQLite3+%28ext+mem%29&quot; /&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;http://chart.apis.google.com/chart?chtt=Read+speed+%28rows%2Fsecond%29&amp;amp;chxl=1:|SQLite3+%28ext+mem%29|SQLite3+%28ext+off%29|SQLite3+%28ext+full%29|TObjectList+%28virtual%29|TObjectList+%28static%29|SQLite3+%28mem%29|SQLite3+%28file+off%29|SQLite3+%28file+full%29&amp;amp;chxt=x,y&amp;amp;chbh=a&amp;amp;chs=600x400&amp;amp;cht=bhg&amp;amp;chco=3D7930,3D8930,309F30,6070F0,5070E0,40C355,65D055,80C1A2,3D7930,3D8930,F05050,F04050,F04040,F01040,F0A280&amp;amp;chxr=0,0,885269&amp;amp;chds=0,885269,0,885269,0,885269,0,885269,0,885269,0,885269,0,885269,0,885269&amp;amp;chd=t:28527,28927,127740,335053,334739,132594,138159,139567|516689,513769,529100,869262,410374,258371,260892,254919|521159,519156,523176,879352,885269,506277,507717,516208&amp;amp;chdl=By+one|All+Virtual|All+Direct&quot; /&gt;&lt;/p&gt;
&lt;table&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt; &lt;/td&gt;
&lt;td&gt;&lt;strong&gt;By one&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;All Virtual&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;All Direct&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;SQLite3 (file full)&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;28527&lt;/td&gt;
&lt;td&gt;516689&lt;/td&gt;
&lt;td&gt;521159&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;SQLite3 (file off)&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;28927&lt;/td&gt;
&lt;td&gt;513769&lt;/td&gt;
&lt;td&gt;519156&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;SQLite3 (mem)&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;127740&lt;/td&gt;
&lt;td&gt;529100&lt;/td&gt;
&lt;td&gt;523176&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;TObjectList (static)&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;335053&lt;/td&gt;
&lt;td&gt;869262&lt;/td&gt;
&lt;td&gt;879352&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;TObjectList (virtual)&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;334739&lt;/td&gt;
&lt;td&gt;410374&lt;/td&gt;
&lt;td&gt;885269&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;SQLite3 (ext full)&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;132594&lt;/td&gt;
&lt;td&gt;258371&lt;/td&gt;
&lt;td&gt;506277&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;SQLite3 (ext off)&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;138159&lt;/td&gt;
&lt;td&gt;260892&lt;/td&gt;
&lt;td&gt;507717&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;SQLite3 (ext mem)&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;139567&lt;/td&gt;
&lt;td&gt;254919&lt;/td&gt;
&lt;td&gt;516208&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Under &lt;em&gt;Windows&lt;/em&gt;, the &lt;em&gt;Microsoft&lt;/em&gt; &lt;em&gt;Visual C++&lt;/em&gt;
compiler gives very good results.&lt;br /&gt;
It is a bit faster than the other two, despite a somewhat less efficient
virtual table process.&lt;/p&gt;
&lt;p&gt;As a conclusion, our statically linked implementation sounds like the best
overall approach: best speed for virtual tables (which is the core of our ORM),
and no &lt;a href=&quot;http://blog.synopse.info/post/2010/09/20/Dll-hell%2C-WinSXS-directory-and-Delphi-paradise&quot;&gt;dll
hell&lt;/a&gt;.&lt;br /&gt;
No library to deploy and copy, everything is embedded in the project
executable, ready to run as expected.&lt;/p&gt;
&lt;p&gt;Using external &lt;em&gt;SQLite3&lt;/em&gt; is also the open door to easy cross-platform
of &lt;em&gt;mORMot&lt;/em&gt;.&lt;br /&gt;
First step will be to &lt;a href=&quot;http://synopse.info/fossil/info/65fe490e9d&quot;&gt;finish the 64 bit compatibility of
the framework&lt;/a&gt;, using the official &lt;em&gt;x64&lt;/em&gt; &lt;code&gt;SQLite3.dll&lt;/code&gt;,
which is much easier to work with than linking to &lt;code&gt;.obj&lt;/code&gt; in
Delphi.&lt;/p&gt;
&lt;p&gt;Feedback is &lt;a href=&quot;http://synopse.info/forum/viewtopic.php?pid=6223#p6223&quot;&gt;welcome in our
forum&lt;/a&gt;.&lt;/p&gt;</description>
    
    
    
      </item>
    
  <item>
    <title>Interface-based service sample: remote SQL access</title>
    <link>http://blog.synopse.info/post/2013/02/17/Interface-based-service-sample%3A-remote-SQL-access</link>
    <guid isPermaLink="false">urn:md5:15fe48359fd9ba1bcd73d6ae0eed9e04</guid>
    <pubDate>Sun, 17 Feb 2013 13:14:00 +0100</pubDate>
    <dc:creator>A.Bouchez</dc:creator>
        <category>mORMot Framework</category>
        <category>AJAX</category><category>blog</category><category>Database</category><category>Delphi</category><category>Documentation</category><category>dynamic array</category><category>exception</category><category>HTTP</category><category>interface</category><category>JSON</category><category>mORMot</category><category>MSSQL</category><category>NexusDB</category><category>ODBC</category><category>OleDB</category><category>Oracle</category><category>ORM</category><category>Parsing</category><category>performance</category><category>SOA</category><category>Source</category><category>SQL</category><category>SQLite3</category><category>SynDB</category>    
    <description>&lt;p&gt;You will find in the &lt;code&gt;SQLite3\Sample\16 - Execute SQL via
services&lt;/code&gt; folder of &lt;em&gt;mORMot&lt;/em&gt; source code a Client-Server sample
able to access any external database via JSON and HTTP.&lt;br /&gt;
It is a good demonstration of how to use an &lt;a href=&quot;http://blog.synopse.info/post/2012/03/07/Interface-based-services&quot;&gt;interface-based service&lt;/a&gt; between
a client and a server.&lt;br /&gt;
It will also show how our &lt;code&gt;SynDB&lt;/code&gt; classes have a quite abstract
design, and are easy to work with, whatever database provider you need to
use.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;http://blog.synopse.info/public/mORMot/marmot2.png&quot; alt=&quot;&quot; title=&quot;mORMot BW, fév. 2013&quot; /&gt;&lt;/p&gt;
&lt;p&gt;The corresponding service contract has been defined:&lt;/p&gt;
&lt;pre&gt;
  TRemoteSQLEngine = (rseOleDB, rseODBC, rseOracle, rseSQlite3, rseJet, rseMSSQL);
&lt;br /&gt;  IRemoteSQL = &lt;strong&gt;interface&lt;/strong&gt;(IInvokable)
    ['{9A60C8ED-CEB2-4E09-87D4-4A16F496E5FE}']
    &lt;strong&gt;procedure&lt;/strong&gt; Connect(aEngine: TRemoteSQLEngine; &lt;strong&gt;const&lt;/strong&gt; aServerName, aDatabaseName,
      aUserID, aPassWord: RawUTF8);
    &lt;strong&gt;function&lt;/strong&gt; GetTableNames: TRawUTF8DynArray;
    &lt;strong&gt;function&lt;/strong&gt; Execute(&lt;strong&gt;const&lt;/strong&gt; aSQL: RawUTF8; aExpectResults, aExpanded: Boolean): RawJSON;
  &lt;strong&gt;end&lt;/strong&gt;;
&lt;/pre&gt;
&lt;p&gt;Purpose of this service is:&lt;br /&gt;
- To &lt;code&gt;Connect()&lt;/code&gt; to external databases, given the parameters of a
standard &lt;code&gt;TSQLDBConnectionProperties. Create()&lt;/code&gt; constructor;&lt;br /&gt;
- Retrieve all table names of this external database as a list;&lt;br /&gt;
- Execute any SQL statement, returning the content as JSON array, ready to be
consumed by AJAX applications (if &lt;code&gt;aExpanded&lt;/code&gt; is &lt;code&gt;true&lt;/code&gt;),
or a Delphi client (e.g. via a &lt;code&gt;TSQLTableJSON&lt;/code&gt; and the
&lt;code&gt;mORMotUI&lt;/code&gt; unit).&lt;/p&gt;
&lt;p&gt;Of course, this service will be define as &lt;code&gt;sicClientDriven&lt;/code&gt; mode,
that is, the framework will be able to manage a client-driven
&lt;code&gt;TSQLDBProperties&lt;/code&gt; instance life time.&lt;/p&gt;
&lt;p&gt;Benefit of this service is that no database connection is required on the
client side: a regular HTTP connection is enough.&lt;br /&gt;
No need to install nor configure any database provider, and full SQL access to
the remote databases.&lt;/p&gt;
&lt;p&gt;Due to our optimized JSON serialization, it will probably be faster to work
with such plain HTTP / JSON services, instead of a database connection through
a VPN. In fact, database connections are made to work on a local network, and
do not like high-latency connections, which are typical on the Internet.&lt;/p&gt;    &lt;p&gt;Note that the &lt;code&gt;Execute()&lt;/code&gt; method returns a &lt;code&gt;RawJSON&lt;/code&gt;
kind of variable, which is in fact a sub-type of &lt;code&gt;RawUTF8&lt;/code&gt;. Its
purpose is to transmit the UTF-8 encoded content directly, with no translation
to a JSON string, as would be the case with a &lt;code&gt;RawUTF8&lt;/code&gt; variable. In
fact, escaping some JSON array within a JSON string is quite verbose. Using
&lt;code&gt;RawJSON&lt;/code&gt; in this case ensure the best client-side and server-side
speed, and also reduce the transmission bandwidth.&lt;/p&gt;
&lt;p&gt;The server part is quite easy to follow:&lt;/p&gt;
&lt;pre&gt;
&lt;strong&gt;type&lt;/strong&gt;
  TServiceRemoteSQL = &lt;strong&gt;class&lt;/strong&gt;(TInterfacedObject, IRemoteSQL)
  &lt;strong&gt;protected&lt;/strong&gt;
    fProps: TSQLDBConnectionProperties;
  &lt;strong&gt;public&lt;/strong&gt;
    &lt;strong&gt;destructor&lt;/strong&gt; Destroy; &lt;strong&gt;override&lt;/strong&gt;;
  &lt;strong&gt;public&lt;/strong&gt; &lt;em&gt;// implements IRemoteSQL methods&lt;/em&gt;
    &lt;strong&gt;procedure&lt;/strong&gt; Connect(aEngine: TRemoteSQLEngine; &lt;strong&gt;const&lt;/strong&gt; aServerName, aDatabaseName,
      aUserID, aPassWord: RawUTF8);
    &lt;strong&gt;function&lt;/strong&gt; GetTableNames: TRawUTF8DynArray;
    &lt;strong&gt;function&lt;/strong&gt; Execute(&lt;strong&gt;const&lt;/strong&gt; aSQL: RawUTF8; aExpectResults, aExpanded: Boolean): RawJSON;
  &lt;strong&gt;end&lt;/strong&gt;;
&lt;br /&gt; &lt;em&gt;{ TServiceRemoteSQL }&lt;/em&gt;&lt;br /&gt;&lt;strong&gt;procedure&lt;/strong&gt; TServiceRemoteSQL.Connect(aEngine: TRemoteSQLEngine; &lt;strong&gt;const&lt;/strong&gt; aServerName, aDatabaseName, aUserID, aPassWord: RawUTF8);
&lt;strong&gt;const&lt;/strong&gt; &lt;em&gt;// rseOleDB, rseODBC, rseOracle, rseSQlite3, rseJet, rseMSSQL&lt;/em&gt;
  TYPES: &lt;strong&gt;array&lt;/strong&gt;[TRemoteSQLEngine] &lt;strong&gt;of&lt;/strong&gt; TSQLDBConnectionPropertiesClass = (
     TOleDBConnectionProperties, TODBCConnectionProperties,
     TSQLDBOracleConnectionProperties, TSQLDBSQLite3ConnectionProperties,
     TOleDBJetConnectionProperties, TOleDBMSSQL2008ConnectionProperties);
&lt;strong&gt;begin&lt;/strong&gt;
  &lt;strong&gt;if&lt;/strong&gt; fProps&amp;lt;&amp;gt;&lt;strong&gt;nil then&lt;/strong&gt;
    &lt;strong&gt;raise&lt;/strong&gt; Exception.Create('Connect called more than once');
  fProps := TYPES[aEngine].Create(aServerName,aDatabaseName,aUserID,aPassWord);
&lt;strong&gt;end&lt;/strong&gt;;
&lt;br /&gt;&lt;strong&gt;function&lt;/strong&gt; TServiceRemoteSQL.Execute(&lt;strong&gt;const&lt;/strong&gt; aSQL: RawUTF8; aExpectResults, aExpanded: Boolean): RawJSON;
&lt;strong&gt;var&lt;/strong&gt; res: ISQLDBRows;
&lt;strong&gt;begin&lt;/strong&gt;
  &lt;strong&gt;if&lt;/strong&gt; fProps=&lt;strong&gt;nil then&lt;/strong&gt;
    &lt;strong&gt;raise&lt;/strong&gt; Exception.Create('Connect call required before Execute');
  res := fProps.ExecuteInlined(aSQL,aExpectResults);
  &lt;strong&gt;if&lt;/strong&gt; res=&lt;strong&gt;nil then&lt;/strong&gt;
    result := '' &lt;strong&gt;else&lt;/strong&gt;
    result := res.FetchAllAsJSON(aExpanded);
&lt;strong&gt;end&lt;/strong&gt;;
&lt;br /&gt;&lt;strong&gt;function&lt;/strong&gt; TServiceRemoteSQL.GetTableNames: TRawUTF8DynArray;
&lt;strong&gt;begin&lt;/strong&gt;
  &lt;strong&gt;if&lt;/strong&gt; fProps=&lt;strong&gt;nil then&lt;/strong&gt;
    &lt;strong&gt;raise&lt;/strong&gt; Exception.Create('Connect call required before GetTableNames');
  fProps.GetTableNames(result);
&lt;strong&gt;end&lt;/strong&gt;;
&lt;br /&gt;&lt;strong&gt;destructor&lt;/strong&gt; TServiceRemoteSQL.Destroy;
&lt;strong&gt;begin&lt;/strong&gt;
  FreeAndNil(fProps);
  &lt;strong&gt;inherited&lt;/strong&gt;;
&lt;strong&gt;end&lt;/strong&gt;;
&lt;/pre&gt;
&lt;p&gt;Any exception during &lt;code&gt;SynDB&lt;/code&gt; process, or raised manually in case
of wrong use case will be transmitted to the client, just as expected. The
&lt;code&gt;fProps&lt;/code&gt; instance life-time is handled by the client, so all we need
is to release its pointer in the service implementation destructor.&lt;/p&gt;
&lt;p&gt;From the client point of view, it will be consumed as such:&lt;/p&gt;
&lt;pre&gt;
&lt;strong&gt;procedure&lt;/strong&gt; TMainForm.FormShow(Sender: TObject);
  (...)
  fModel := TSQLModel.Create([],ROOT_NAME);
  &lt;span style=&quot;background-color:yellow;&quot;&gt;fClient := TSQLHttpClient.Create('localhost','888',fModel);&lt;/span&gt;
  &lt;strong&gt;if not&lt;/strong&gt; fClient.ServerTimeStampSynchronize &lt;strong&gt;then begin&lt;/strong&gt;
    ShowLastClientError(fClient,'Please run Project16ServerHttp.exe');
    Close;
    exit;
  &lt;strong&gt;end&lt;/strong&gt;;
  &lt;span style=&quot;background-color:yellow;&quot;&gt;&lt;strong&gt;if&lt;/strong&gt; (&lt;strong&gt;not&lt;/strong&gt; fClient.SetUser('User','synopse'))  &lt;strong&gt;or&lt;/strong&gt;&lt;/span&gt;
     &lt;span style=&quot;background-color:yellow;&quot;&gt;(&lt;strong&gt;not&lt;/strong&gt; fClient.ServiceRegisterClientDriven(TypeInfo(IRemoteSQL),fService)) &lt;strong&gt;then begin&lt;/strong&gt;&lt;/span&gt;
    ShowLastClientError(fClient,'Remote service not available on server');
    Close;
    exit;
  &lt;strong&gt;end&lt;/strong&gt;;
&lt;strong&gt;end&lt;/strong&gt;;
&lt;/pre&gt;
&lt;p&gt;Note the use of &lt;code&gt;ShowLastClientError()&lt;/code&gt; function of
&lt;code&gt;mORMotUILogin&lt;/code&gt; unit, which is able to use our
&lt;code&gt;SynTaskDialog&lt;/code&gt; unit to report standard and detailed information
about the latest error.&lt;/p&gt;
&lt;p&gt;Note that in this sample, no table has been defined within the ORM model. It
is not necessary, since all external process will take place at the SQL level.
As we need authentication (see the call to &lt;code&gt;fClient.SetUser&lt;/code&gt;
method), the ORM core will by itself add the &lt;code&gt;TSQLAuthUser&lt;/code&gt; and
&lt;code&gt;TSQLAuthGroup&lt;/code&gt; tables to the model - no need to add them
explicitly.&lt;/p&gt;
&lt;p&gt;From now on, we have a &lt;code&gt;fService: IRemoteSQL&lt;/code&gt; instance available
to connect and process any remote SQL request.&lt;/p&gt;
&lt;pre&gt;
&lt;strong&gt;procedure&lt;/strong&gt; TMainForm.btnOpenClick(Sender: TObject);
&lt;strong&gt;var&lt;/strong&gt; TableNames: TRawUTF8DynArray;
  (...)
  &lt;strong&gt;with&lt;/strong&gt; fSettings &lt;strong&gt;do&lt;/strong&gt;
    &lt;span style=&quot;background-color:yellow;&quot;&gt;fService.Connect(Engine,ServerName,DatabaseName,UserID,PassWord);&lt;/span&gt;
  &lt;span style=&quot;background-color:yellow;&quot;&gt;TableNames := fService.GetTableNames;&lt;/span&gt;
  cbbTableNames.Items.Text := UTF8ToString(RawUTF8ArrayToCSV(TableNames,#13#10));
  (...)
&lt;/pre&gt;
&lt;p&gt;Now we are connected to the database via the remote service, and we
retrieved the table names in a &lt;code&gt;TComboBox&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Then a particular SQL statement can be executed as such:&lt;/p&gt;
&lt;pre&gt;
&lt;strong&gt;procedure&lt;/strong&gt; TMainForm.btnExecuteClick(Sender: TObject);
&lt;strong&gt;var&lt;/strong&gt; SQL: RawUTF8;
&lt;strong&gt;begin&lt;/strong&gt;
  SQL := trim(StringToUTF8(mmoQuery.Text));
  Screen.Cursor := crHourGlass;
  &lt;strong&gt;try&lt;/strong&gt;
    &lt;strong&gt;try&lt;/strong&gt;
      &lt;strong&gt;if&lt;/strong&gt; isSelect(pointer(SQL)) &lt;strong&gt;then begin&lt;/strong&gt;
        &lt;span style=&quot;background-color:yellow;&quot;&gt;fTableJSON := fService.Execute(SQL,True,False);&lt;/span&gt;
        TSQLTableToGrid.Create(drwgrdData,
          TSQLTableJSON.Create([],SQL,pointer(fTableJSON),Length(fTableJSON)),fClient);
      &lt;strong&gt;end else&lt;/strong&gt;
        fService.Execute(SQL,False,False);
    &lt;strong&gt;except&lt;/strong&gt;
      on E: Exception &lt;strong&gt;do&lt;/strong&gt;
        ShowException(E);
    &lt;strong&gt;end&lt;/strong&gt;;
  &lt;strong&gt;finally&lt;/strong&gt;
    Screen.Cursor := crDefault;
  &lt;strong&gt;end&lt;/strong&gt;;
&lt;strong&gt;end&lt;/strong&gt;;
&lt;/pre&gt;
&lt;p&gt;Here, &lt;code&gt;TSQLTableToGrid.Create()&lt;/code&gt;, from the &lt;code&gt;mORMotUI&lt;/code&gt;
unit, will &amp;quot;inject&amp;quot; the returned data to a standard &lt;code&gt;TDrawGrid&lt;/code&gt;,
using a &lt;code&gt;TSQLTableJSON&lt;/code&gt; instance to unserialize the returned JSON
content.&lt;/p&gt;
&lt;p&gt;Note that in case of any exception (connection failure, or server side
error, e.g. wrong SQL statement), the &lt;code&gt;ShowExecption()&lt;/code&gt; method is
used to notify the user with appropriate information.&lt;/p&gt;
&lt;p&gt;Feedback is &lt;a href=&quot;http://synopse.info/forum/viewtopic.php?pid=6717#p6717&quot;&gt;welcome on our
forum&lt;/a&gt;.&lt;/p&gt;</description>
    
    
    
      </item>
    
  <item>
    <title>Introducing ZEOS, UniDAC, NexusDB, BDE, any TDataset to SynDB and mORMot's ORM</title>
    <link>http://blog.synopse.info/post/2013/02/12/Introducing-ZEOS%2C-UniDAC%2C-NexusDB%2C-BDE%2C-any-TDataset-to-SynDB-and-mORMot-s-ORM</link>
    <guid isPermaLink="false">urn:md5:605b2cdd5fb64f31cb9b478c1c113d5c</guid>
    <pubDate>Tue, 12 Feb 2013 17:42:00 +0100</pubDate>
    <dc:creator>A.Bouchez</dc:creator>
        <category>mORMot Framework</category>
        <category>Database</category><category>Delphi</category><category>JSON</category><category>mORMot</category><category>MSSQL</category><category>NexusDB</category><category>ODBC</category><category>OleDB</category><category>Oracle</category><category>ORM</category><category>performance</category><category>Repository</category><category>Rest</category><category>Source</category><category>SQL</category><category>SQLite3</category><category>SynDB</category><category>TDataSet</category><category>transaction</category><category>UniDAC</category><category>ZEOS</category>    
    <description>&lt;p&gt;Up to now, our &lt;code&gt;SynDB&lt;/code&gt; database classes were handling
&lt;em&gt;ODBC&lt;/em&gt;, &lt;em&gt;OleDB&lt;/em&gt; providers and direct &lt;em&gt;Oracle&lt;/em&gt; or
&lt;em&gt;SQLite3&lt;/em&gt; connection.&lt;/p&gt;
&lt;p&gt;We have added a &lt;code&gt;DB.pas&lt;/code&gt; based layer, ready to be used with
&lt;em&gt;&lt;a href=&quot;http://www.devart.com/unidac/&quot;&gt;UniDAC&lt;/a&gt;&lt;/em&gt;, &lt;em&gt;&lt;a href=&quot;http://www.nexusdb.com&quot;&gt;NexusDB&lt;/a&gt;&lt;/em&gt;, or the &lt;em&gt;BDE&lt;/em&gt;.&lt;br /&gt;
Any other &lt;code&gt;TDataset&lt;/code&gt; based component is ready to be interfaced,
including &lt;em&gt;UIB&lt;/em&gt;, &lt;em&gt;AnyDAC&lt;/em&gt; or &lt;em&gt;DBExpress&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;http://blog.synopse.info/public/mORMot/mORMotDatabase.png&quot; alt=&quot;&quot; title=&quot;mORMot Database, avr. 2013&quot; /&gt;&lt;/p&gt;
&lt;p&gt;The &lt;em&gt;ZEOS&lt;/em&gt; library (in its latest &lt;a href=&quot;http://sourceforge.net/projects/zeoslib/files/Zeos%20Database%20Objects/zeosdbo-7.0.3-stable/&quot;&gt;7.0.3
stable version&lt;/a&gt;, which works from Delphi 7 up to XE3) has also been
interfaced, but without the &lt;code&gt;TDataset&lt;/code&gt;/&lt;code&gt;DB.pas&lt;/code&gt; layer:
our &lt;code&gt;SynDBZEOS.pas&lt;/code&gt; unit calls the ZDBC layer, which is not
tied to &lt;code&gt;DB.pas&lt;/code&gt; nor its RAD components, and is therefore
faster. By the way, it will work also with the &lt;em&gt;Starter edition&lt;/em&gt; of
Delphi (which does not include the DB components) - just like the other
&amp;quot;regular&amp;quot; &lt;code&gt;SynDB&lt;/code&gt; classes.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;http://blog.synopse.info/public/mORMot/.641-03461407w_m.jpg&quot; alt=&quot;&quot; title=&quot;mORMot photo, fév. 2013&quot; /&gt;&lt;/p&gt;
&lt;p&gt;This is a work in progress, any testing and feedback is welcome!&lt;br /&gt;
We had to circumvent some particularities of the libraries, but I guess we have
something interesting.&lt;/p&gt;
&lt;p&gt;A dedicated &amp;quot;&lt;em&gt;SynDBDataset&lt;/em&gt;&amp;quot; sub-folder has been created &lt;a href=&quot;http://synopse.info/fossil/dir?ci=tip&quot;&gt;in the repository&lt;/a&gt;, to contain all
&lt;code&gt;SynDBDataset.pas&lt;/code&gt;-based database providers.&lt;br /&gt;
&lt;code&gt;SynDBNexusDB.pas&lt;/code&gt; unit has been moved within this sub-folder,
as &lt;code&gt;SynDBUniDAC.pas&lt;/code&gt; + &lt;code&gt;SynDBBDE.pas&lt;/code&gt; units have
been added.&lt;br /&gt;
&lt;code&gt;SynDBZeos.pas&lt;/code&gt; has a direct access to the &lt;em&gt;ZDBC&lt;/em&gt; layer, so
is not part of the &amp;quot;&lt;em&gt;SynDBDataset&lt;/em&gt;&amp;quot; sub-folder.&lt;/p&gt;
&lt;p&gt;Here is some benchmark, mainly about &lt;em&gt;Oracle&lt;/em&gt; and
&lt;em&gt;SQlite3&lt;/em&gt; database access.&lt;br /&gt;
Of course, our direct &lt;code&gt;SynDBOracle&lt;/code&gt; / &lt;code&gt;SynDBSQLite3&lt;/code&gt;
layers are the fastest around, and we can see that ZDBC layer is sometimes more
efficient than the &lt;code&gt;TDataset&lt;/code&gt; components.&lt;/p&gt;    &lt;p&gt;This preliminary results came from the &lt;a href=&quot;http://blog.synopse.info/post/2013/01/28/External-database-speed-improvements&quot;&gt;same hardware than
previously used on this blog&lt;/a&gt;.&lt;br /&gt;
In short: notebook with a SSD and Core i7 mobile.&lt;/p&gt;
&lt;p&gt;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 &lt;em&gt;mORMot&lt;/em&gt; database layer.&lt;br /&gt;
Purpose here is not to say that one library is better or faster than another,
but publish a snapshot of &lt;em&gt;mORMot&lt;/em&gt; persistence layer abilities.&lt;br /&gt;
In this timing, we do not benchmark only the &amp;quot;pure&amp;quot; SQL-DB layer access
(&lt;code&gt;SynDB*&lt;/code&gt; units), but the whole Client-Server ORM of our framework:
process below includes read and write RTTI access of a &lt;code&gt;TSQLRecord&lt;/code&gt;,
JSON marshalling, CRUD/REST routing, virtual cross-database layer, SQL
on-the-fly translation. We just bypass the communication layer, since
&lt;code&gt;TSQLRestClient&lt;/code&gt; and &lt;code&gt;TSQLRestServer&lt;/code&gt; are run in-process,
in the same thread - as a &lt;code&gt;TSQLRestServerDB&lt;/code&gt; instance. So you have
here some raw performance testimony of our framework's ORM and RESTful
core.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Jet/MSAccess&lt;/em&gt; database engine is accessed via OleDB.&lt;br /&gt;
&lt;em&gt;NexusDB&lt;/em&gt; is the &lt;a href=&quot;http://www.nexusdb.com/support/index.php?q=FreeEmbedded&quot;&gt;free embedded
edition&lt;/a&gt;, which is a perfect match for a Client-Server ORM framework like
&lt;em&gt;mORMot&lt;/em&gt;.&lt;br /&gt;
&lt;em&gt;Oracle&lt;/em&gt; server is a remote 11g instance, accessed with a &amp;quot;slow&amp;quot; 100 MB
network.&lt;br /&gt;
&lt;em&gt;SQLite3&lt;/em&gt; is our static embedded engine, either as internal or external
database, or the &lt;a href=&quot;http://www.sqlite.org/download.html&quot;&gt;latest 3.7.15.2
official&lt;/a&gt; &lt;code&gt;sqlite3.dll&lt;/code&gt; library, for &lt;em&gt;ZEOS&lt;/em&gt; and
&lt;em&gt;UniDAC&lt;/em&gt;.&lt;br /&gt;
&lt;em&gt;TObjectList&lt;/em&gt; is our in-memory optimized engine, with hashed indexes,
and able to persist its data as JSON file or an optimized and compressed binary
content.&lt;/p&gt;
&lt;h3&gt;Insertion speed&lt;/h3&gt;
&lt;p&gt;We use the sample provided within the source code tree, i.e. &amp;quot;15 - External
DB performance&amp;quot;.&lt;/p&gt;
&lt;table&gt;
&lt;tbody&gt;
&lt;tr align=&quot;center&quot;&gt;
&lt;td&gt; &lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Direct&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Batch&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Trans&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Batch Trans&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr align=&quot;center&quot;&gt;
&lt;td&gt;&lt;strong&gt;SQLite3 (file full)&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;536&lt;/td&gt;
&lt;td&gt;525&lt;/td&gt;
&lt;td&gt;93687&lt;/td&gt;
&lt;td&gt;113527&lt;/td&gt;
&lt;/tr&gt;
&lt;tr align=&quot;center&quot;&gt;
&lt;td&gt;&lt;strong&gt;SQLite3 (file off)&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;941&lt;/td&gt;
&lt;td&gt;610&lt;/td&gt;
&lt;td&gt;94222&lt;/td&gt;
&lt;td&gt;98590&lt;/td&gt;
&lt;/tr&gt;
&lt;tr align=&quot;center&quot;&gt;
&lt;td&gt;&lt;strong&gt;SQLite3 (mem)&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;84722&lt;/td&gt;
&lt;td&gt;104727&lt;/td&gt;
&lt;td&gt;100425&lt;/td&gt;
&lt;td&gt;126974&lt;/td&gt;
&lt;/tr&gt;
&lt;tr align=&quot;center&quot;&gt;
&lt;td&gt;&lt;strong&gt;TObjectList (static)&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;298560&lt;/td&gt;
&lt;td&gt;423657&lt;/td&gt;
&lt;td&gt;300951&lt;/td&gt;
&lt;td&gt;385089&lt;/td&gt;
&lt;/tr&gt;
&lt;tr align=&quot;center&quot;&gt;
&lt;td&gt;&lt;strong&gt;TObjectList (virtual)&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;298721&lt;/td&gt;
&lt;td&gt;445473&lt;/td&gt;
&lt;td&gt;299293&lt;/td&gt;
&lt;td&gt;444207&lt;/td&gt;
&lt;/tr&gt;
&lt;tr align=&quot;center&quot;&gt;
&lt;td&gt;&lt;strong&gt;SQLite3 (ext full)&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;262&lt;/td&gt;
&lt;td&gt;259&lt;/td&gt;
&lt;td&gt;94916&lt;/td&gt;
&lt;td&gt;120293&lt;/td&gt;
&lt;/tr&gt;
&lt;tr align=&quot;center&quot;&gt;
&lt;td&gt;&lt;strong&gt;SQLite3 (ext off)&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;337&lt;/td&gt;
&lt;td&gt;330&lt;/td&gt;
&lt;td&gt;103941&lt;/td&gt;
&lt;td&gt;112336&lt;/td&gt;
&lt;/tr&gt;
&lt;tr align=&quot;center&quot;&gt;
&lt;td&gt;&lt;strong&gt;SQLite3 (ext mem)&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;95418&lt;/td&gt;
&lt;td&gt;119442&lt;/td&gt;
&lt;td&gt;110238&lt;/td&gt;
&lt;td&gt;143135&lt;/td&gt;
&lt;/tr&gt;
&lt;tr align=&quot;center&quot;&gt;
&lt;td&gt;&lt;strong&gt;UniDAC SQlite3&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;239&lt;/td&gt;
&lt;td&gt;253&lt;/td&gt;
&lt;td&gt;7916&lt;/td&gt;
&lt;td&gt;38696&lt;/td&gt;
&lt;/tr&gt;
&lt;tr align=&quot;center&quot;&gt;
&lt;td&gt;&lt;strong&gt;ZEOS SQlite3&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;372&lt;/td&gt;
&lt;td&gt;374&lt;/td&gt;
&lt;td&gt;362&lt;/td&gt;
&lt;td&gt;467&lt;/td&gt;
&lt;/tr&gt;
&lt;tr align=&quot;center&quot;&gt;
&lt;td&gt;&lt;strong&gt;Oracle&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;538&lt;/td&gt;
&lt;td&gt;62295&lt;/td&gt;
&lt;td&gt;1228&lt;/td&gt;
&lt;td&gt;62156&lt;/td&gt;
&lt;/tr&gt;
&lt;tr align=&quot;center&quot;&gt;
&lt;td&gt;&lt;strong&gt;ODBC Oracle&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;639&lt;/td&gt;
&lt;td&gt;605&lt;/td&gt;
&lt;td&gt;1743&lt;/td&gt;
&lt;td&gt;1606&lt;/td&gt;
&lt;/tr&gt;
&lt;tr align=&quot;center&quot;&gt;
&lt;td&gt;&lt;strong&gt;ZEOS Oracle&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;441&lt;/td&gt;
&lt;td&gt;424&lt;/td&gt;
&lt;td&gt;1109&lt;/td&gt;
&lt;td&gt;1140&lt;/td&gt;
&lt;/tr&gt;
&lt;tr align=&quot;center&quot;&gt;
&lt;td&gt;&lt;strong&gt;UniDAC Oracle&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;528&lt;/td&gt;
&lt;td&gt;557&lt;/td&gt;
&lt;td&gt;1061&lt;/td&gt;
&lt;td&gt;1237&lt;/td&gt;
&lt;/tr&gt;
&lt;tr align=&quot;center&quot;&gt;
&lt;td&gt;&lt;strong&gt;BDE Oracle&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;489&lt;/td&gt;
&lt;td&gt;511&lt;/td&gt;
&lt;td&gt;1024&lt;/td&gt;
&lt;td&gt;1003&lt;/td&gt;
&lt;/tr&gt;
&lt;tr align=&quot;center&quot;&gt;
&lt;td&gt;&lt;strong&gt;Jet&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;4243&lt;/td&gt;
&lt;td&gt;4442&lt;/td&gt;
&lt;td&gt;4924&lt;/td&gt;
&lt;td&gt;4982&lt;/td&gt;
&lt;/tr&gt;
&lt;tr align=&quot;center&quot;&gt;
&lt;td&gt;&lt;strong&gt;NexusDB&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;4697&lt;/td&gt;
&lt;td&gt;6711&lt;/td&gt;
&lt;td&gt;5723&lt;/td&gt;
&lt;td&gt;8786&lt;/td&gt;
&lt;/tr&gt;
&lt;tr align=&quot;center&quot;&gt;
&lt;td&gt;&lt;strong&gt;ZEOS Firebird&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;1791&lt;/td&gt;
&lt;td&gt;1870&lt;/td&gt;
&lt;td&gt;6522&lt;/td&gt;
&lt;td&gt;7213&lt;/td&gt;
&lt;/tr&gt;
&lt;tr align=&quot;center&quot;&gt;
&lt;td&gt;&lt;strong&gt;UniDAC Firebird&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;3670&lt;/td&gt;
&lt;td&gt;7135&lt;/td&gt;
&lt;td&gt;4751&lt;/td&gt;
&lt;td&gt;10125&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;img src=&quot;http://chart.apis.google.com/chart?chtt=Insertion+speed+%28rows%2Fsecond%29&amp;amp;chxl=1:|Batch+Trans|Trans|Batch|Direct&amp;amp;chxt=x,y&amp;amp;chbh=a&amp;amp;chs=600x400&amp;amp;cht=bhg&amp;amp;chco=3D7930,3D8930,309F30,6070F0,5070E0,40C355,65D055,80C1A2,3D7930,3D8930,F05050,F04050,F04040,F01040,F0A280&amp;amp;chxr=0,0,445473&amp;amp;chds=0,445473,0,445473,0,445473,0,445473,0,445473&amp;amp;chd=t:536,525,93687,113527|941,610,94222,98590|84722,104727,100425,126974|298560,423657,300951,385089|298721,445473,299293,444207|262,259,94916,120293|337,330,103941,112336|95418,119442,110238,143135|239,253,7916,38696|372,374,362,467|538,62295,1228,62156|639,605,1743,1606|441,424,1109,1140|528,557,1061,1237|489,511,1024,1003|4243,4442,4924,4982|4697,6711,5723,8786|1791,1870,6522,7213|3670,7135,4751,10125&amp;amp;chdl=SQLite3+%28file+full%29|SQLite3+%28file+off%29|SQLite3+%28mem%29|TObjectList+%28static%29|TObjectList+%28virtual%29|SQLite3+%28ext+full%29|SQLite3+%28ext+off%29|SQLite3+%28ext+mem%29|UniDAC+SQlite3|ZEOS+SQlite3|Oracle|ODBC+Oracle|ZEOS+Oracle|UniDAC+Oracle|BDE+Oracle|Jet|NexusDB|ZEOS+Firebird|UniDAC+Firebird&quot; /&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;http://chart.apis.google.com/chart?chtt=Insertion+speed+%28rows%2Fsecond%29&amp;amp;chxl=1:|UniDAC+Firebird|ZEOS+Firebird|NexusDB|Jet|BDE+Oracle|UniDAC+Oracle|ZEOS+Oracle|ODBC+Oracle|Oracle|ZEOS+SQlite3|UniDAC+SQlite3|SQLite3+%28ext+mem%29|SQLite3+%28ext+off%29|SQLite3+%28ext+full%29|TObjectList+%28virtual%29|TObjectList+%28static%29|SQLite3+%28mem%29|SQLite3+%28file+off%29|SQLite3+%28file+full%29&amp;amp;chxt=x,y&amp;amp;chbh=a&amp;amp;chs=600x400&amp;amp;cht=bhg&amp;amp;chco=3D7930,3D8930,309F30,6070F0,5070E0,40C355,65D055,80C1A2,3D7930,3D8930,F05050,F04050,F04040,F01040,F0A280&amp;amp;chxr=0,0,445473&amp;amp;chds=0,445473,0,445473,0,445473,0,445473,0,445473,0,445473,0,445473,0,445473,0,445473,0,445473,0,445473,0,445473,0,445473,0,445473,0,445473,0,445473,0,445473,0,445473,0,445473&amp;amp;chd=t:536,941,84722,298560,298721,262,337,95418,239,372,538,639,441,528,489,4243,4697,1791,3670|525,610,104727,423657,445473,259,330,119442,253,374,62295,605,424,557,511,4442,6711,1870,7135|93687,94222,100425,300951,299293,94916,103941,110238,7916,362,1228,1743,1109,1061,1024,4924,5723,6522,4751|113527,98590,126974,385089,444207,120293,112336,143135,38696,467,62156,1606,1140,1237,1003,4982,8786,7213,10125&amp;amp;chdl=Direct|Batch|Trans|Batch+Trans&quot; /&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;NexusDB&lt;/em&gt; has a pretty good insertion speed, but no &amp;quot;BATCH&amp;quot; mode, nor
prepared statement re-use. But not bad for such a small unit.&lt;br /&gt;
&lt;em&gt;ZEOS&lt;/em&gt; also lacks of some optimizations like prepared statement cache,
but does work well for an Open Source free solution.&lt;/p&gt;
&lt;h3&gt;Read speed&lt;/h3&gt;
&lt;p&gt;Read speed is comparable to insertion speed.&lt;br /&gt;
Depending on the design of each library, results are similar.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;BDE&lt;/em&gt; performance is not so good, indeed. When working with Oracle,
it is pretty slow, especially when retrieving data.&lt;br /&gt;
But it (still) works!&lt;/p&gt;
&lt;p&gt;Both &lt;em&gt;Jet/MSAccess&lt;/em&gt; and &lt;em&gt;NexusDB&lt;/em&gt; are pretty good, as embedded
engines, for reading.&lt;br /&gt;
Of course, our direct &lt;em&gt;SQlite3&lt;/em&gt; or in-memory &lt;code&gt;TObjectList&lt;/code&gt;
engines are incredibly fast. Just as usual.&lt;/p&gt;
&lt;table&gt;
&lt;tbody&gt;
&lt;tr align=&quot;center&quot;&gt;
&lt;td&gt; &lt;/td&gt;
&lt;td&gt;&lt;strong&gt;By one&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;All Virtual&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;All Direct&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr align=&quot;center&quot;&gt;
&lt;td&gt;&lt;strong&gt;SQLite3 (file full)&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;26755&lt;/td&gt;
&lt;td&gt;435995&lt;/td&gt;
&lt;td&gt;440683&lt;/td&gt;
&lt;/tr&gt;
&lt;tr align=&quot;center&quot;&gt;
&lt;td&gt;&lt;strong&gt;SQLite3 (file off)&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;26527&lt;/td&gt;
&lt;td&gt;435995&lt;/td&gt;
&lt;td&gt;438519&lt;/td&gt;
&lt;/tr&gt;
&lt;tr align=&quot;center&quot;&gt;
&lt;td&gt;&lt;strong&gt;SQLite3 (mem)&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;126253&lt;/td&gt;
&lt;td&gt;438711&lt;/td&gt;
&lt;td&gt;423155&lt;/td&gt;
&lt;/tr&gt;
&lt;tr align=&quot;center&quot;&gt;
&lt;td&gt;&lt;strong&gt;TObjectList (static)&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;289955&lt;/td&gt;
&lt;td&gt;689369&lt;/td&gt;
&lt;td&gt;681477&lt;/td&gt;
&lt;/tr&gt;
&lt;tr align=&quot;center&quot;&gt;
&lt;td&gt;&lt;strong&gt;TObjectList (virtual)&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;299383&lt;/td&gt;
&lt;td&gt;234126&lt;/td&gt;
&lt;td&gt;707714&lt;/td&gt;
&lt;/tr&gt;
&lt;tr align=&quot;center&quot;&gt;
&lt;td&gt;&lt;strong&gt;SQLite3 (ext full)&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;122524&lt;/td&gt;
&lt;td&gt;202208&lt;/td&gt;
&lt;td&gt;356760&lt;/td&gt;
&lt;/tr&gt;
&lt;tr align=&quot;center&quot;&gt;
&lt;td&gt;&lt;strong&gt;SQLite3 (ext off)&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;137358&lt;/td&gt;
&lt;td&gt;228102&lt;/td&gt;
&lt;td&gt;432376&lt;/td&gt;
&lt;/tr&gt;
&lt;tr align=&quot;center&quot;&gt;
&lt;td&gt;&lt;strong&gt;SQLite3 (ext mem)&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;139209&lt;/td&gt;
&lt;td&gt;228738&lt;/td&gt;
&lt;td&gt;432226&lt;/td&gt;
&lt;/tr&gt;
&lt;tr align=&quot;center&quot;&gt;
&lt;td&gt;&lt;strong&gt;UniDAC SQlite3&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;2001&lt;/td&gt;
&lt;td&gt;74155&lt;/td&gt;
&lt;td&gt;96140&lt;/td&gt;
&lt;/tr&gt;
&lt;tr align=&quot;center&quot;&gt;
&lt;td&gt;&lt;strong&gt;ZEOS SQlite3&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;3486&lt;/td&gt;
&lt;td&gt;81959&lt;/td&gt;
&lt;td&gt;115856&lt;/td&gt;
&lt;/tr&gt;
&lt;tr align=&quot;center&quot;&gt;
&lt;td&gt;&lt;strong&gt;Oracle&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;1753&lt;/td&gt;
&lt;td&gt;77429&lt;/td&gt;
&lt;td&gt;92423&lt;/td&gt;
&lt;/tr&gt;
&lt;tr align=&quot;center&quot;&gt;
&lt;td&gt;&lt;strong&gt;ODBC Oracle&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;1909&lt;/td&gt;
&lt;td&gt;36789&lt;/td&gt;
&lt;td&gt;42530&lt;/td&gt;
&lt;/tr&gt;
&lt;tr align=&quot;center&quot;&gt;
&lt;td&gt;&lt;strong&gt;ZEOS Oracle&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;601&lt;/td&gt;
&lt;td&gt;47028&lt;/td&gt;
&lt;td&gt;55233&lt;/td&gt;
&lt;/tr&gt;
&lt;tr align=&quot;center&quot;&gt;
&lt;td&gt;&lt;strong&gt;UniDAC Oracle&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;653&lt;/td&gt;
&lt;td&gt;25960&lt;/td&gt;
&lt;td&gt;28083&lt;/td&gt;
&lt;/tr&gt;
&lt;tr align=&quot;center&quot;&gt;
&lt;td&gt;&lt;strong&gt;BDE Oracle&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;860&lt;/td&gt;
&lt;td&gt;3870&lt;/td&gt;
&lt;td&gt;4036&lt;/td&gt;
&lt;/tr&gt;
&lt;tr align=&quot;center&quot;&gt;
&lt;td&gt;&lt;strong&gt;Jet&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;2605&lt;/td&gt;
&lt;td&gt;150051&lt;/td&gt;
&lt;td&gt;231792&lt;/td&gt;
&lt;/tr&gt;
&lt;tr align=&quot;center&quot;&gt;
&lt;td&gt;&lt;strong&gt;NexusDB&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;1360&lt;/td&gt;
&lt;td&gt;128816&lt;/td&gt;
&lt;td&gt;204976&lt;/td&gt;
&lt;/tr&gt;
&lt;tr align=&quot;center&quot;&gt;
&lt;td&gt;&lt;strong&gt;ZEOS Firebird&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;2508&lt;/td&gt;
&lt;td&gt;56771&lt;/td&gt;
&lt;td&gt;71822&lt;/td&gt;
&lt;/tr&gt;
&lt;tr align=&quot;center&quot;&gt;
&lt;td&gt;&lt;strong&gt;UniDAC Firebird&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;1850&lt;/td&gt;
&lt;td&gt;66882&lt;/td&gt;
&lt;td&gt;88021&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;img src=&quot;http://chart.apis.google.com/chart?chtt=Read+speed+%28rows%2Fsecond%29&amp;amp;chxl=1:|All+Direct|All+Virtual|By+one&amp;amp;chxt=x,y&amp;amp;chbh=a&amp;amp;chs=600x400&amp;amp;cht=bhg&amp;amp;chco=3D7930,3D8930,309F30,6070F0,5070E0,40C355,65D055,80C1A2,3D7930,3D8930,F05050,F04050,F04040,F01040,F0A280&amp;amp;chxr=0,0,707714&amp;amp;chds=0,707714,0,707714,0,707714&amp;amp;chd=t:26755,435995,440683|26527,435995,438519|126253,438711,423155|289955,689369,681477|299383,234126,707714|122524,202208,356760|137358,228102,432376|139209,228738,432226|2001,74155,96140|3486,81959,115856|1753,77429,92423|1909,36789,42530|601,47028,55233|653,25960,28083|860,3870,4036|2605,150051,231792|1360,128816,204976|2508,56771,71822|1850,66882,88021&amp;amp;chdl=SQLite3+%28file+full%29|SQLite3+%28file+off%29|SQLite3+%28mem%29|TObjectList+%28static%29|TObjectList+%28virtual%29|SQLite3+%28ext+full%29|SQLite3+%28ext+off%29|SQLite3+%28ext+mem%29|UniDAC+SQlite3|ZEOS+SQlite3|Oracle|ODBC+Oracle|ZEOS+Oracle|UniDAC+Oracle|BDE+Oracle|Jet|NexusDB|ZEOS+Firebird|UniDAC+Firebird&quot; /&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;http://chart.apis.google.com/chart?chtt=Read+speed+%28rows%2Fsecond%29&amp;amp;chxl=1:|UniDAC+Firebird|ZEOS+Firebird|NexusDB|Jet|BDE+Oracle|UniDAC+Oracle|ZEOS+Oracle|ODBC+Oracle|Oracle|ZEOS+SQlite3|UniDAC+SQlite3|SQLite3+%28ext+mem%29|SQLite3+%28ext+off%29|SQLite3+%28ext+full%29|TObjectList+%28virtual%29|TObjectList+%28static%29|SQLite3+%28mem%29|SQLite3+%28file+off%29|SQLite3+%28file+full%29&amp;amp;chxt=x,y&amp;amp;chbh=a&amp;amp;chs=600x400&amp;amp;cht=bhg&amp;amp;chco=3D7930,3D8930,309F30,6070F0,5070E0,40C355,65D055,80C1A2,3D7930,3D8930,F05050,F04050,F04040,F01040,F0A280&amp;amp;chxr=0,0,707714&amp;amp;chds=0,707714,0,707714,0,707714,0,707714,0,707714,0,707714,0,707714,0,707714,0,707714,0,707714,0,707714,0,707714,0,707714,0,707714,0,707714,0,707714,0,707714,0,707714,0,707714&amp;amp;chd=t:26755,26527,126253,289955,299383,122524,137358,139209,2001,3486,1753,1909,601,653,860,2605,1360,2508,1850|435995,435995,438711,689369,234126,202208,228102,228738,74155,81959,77429,36789,47028,25960,3870,150051,128816,56771,66882|440683,438519,423155,681477,707714,356760,432376,432226,96140,115856,92423,42530,55233,28083,4036,231792,204976,71822,88021&amp;amp;chdl=By+one|All+Virtual|All+Direct&quot; /&gt;&lt;/p&gt;
&lt;p&gt;We are working on direct integration of &lt;em&gt;Firebird&lt;/em&gt; (either directly
via an unfinished &lt;code&gt;SynDBFirebird.pas&lt;/code&gt; unit, or via &lt;em&gt;ZEOS&lt;/em&gt; /
&lt;em&gt;Unidac&lt;/em&gt; / any &lt;code&gt;TDataset&lt;/code&gt; based component), but we are still
fighting with some configuration issues.&lt;br /&gt;
Any help is welcome. Don't be shy!&lt;/p&gt;
&lt;p&gt;The SAD &lt;em&gt;pdf&lt;/em&gt; (&lt;a href=&quot;http://synopse.info/files/pdf/Synopse%20mORMot%20Framework%20SAD%201.18.pdf&quot;&gt;in
its 1.18 revision&lt;/a&gt;) has been updated to include information about external
database connection via those libraries.&lt;/p&gt;
&lt;p&gt;Feedback is &lt;a href=&quot;http://synopse.info/forum/viewtopic.php?id=1094&quot;&gt;welcome on our forum&lt;/a&gt;.&lt;/p&gt;</description>
    
    
    
      </item>
    
  <item>
    <title>Log to the console</title>
    <link>http://blog.synopse.info/post/2013/02/03/Log-to-the-console</link>
    <guid isPermaLink="false">urn:md5:670d22904e2d926b52db2228f5409751</guid>
    <pubDate>Sun, 03 Feb 2013 14:37:00 +0100</pubDate>
    <dc:creator>A.Bouchez</dc:creator>
        <category>mORMot Framework</category>
        <category>Database</category><category>Delphi</category><category>exception</category><category>GoodPractice</category><category>log</category><category>map</category><category>mORMot</category><category>ORM</category><category>Source</category><category>SQL</category><category>UnitTesting</category>    
    <description>&lt;p&gt;Our framework features an &lt;a href=&quot;http://blog.synopse.info/tag/log&quot;&gt;integrated logging class&lt;/a&gt;,
ready to be enabled for support and statistics.&lt;/p&gt;
&lt;p&gt;For debugging purposes, it could be very handy to output the logging content
to a console window.&lt;br /&gt;
It enables interactive debugging of a Client-Server process, for instance: you
can interact with the Client, then look in real time at the server console
window, and inspect which requests are processed, without the need to open the
log file.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;http://fc05.deviantart.net/fs70/i/2010/190/0/1/marmot_design_by_GigiCave.jpg&quot; alt=&quot;&quot; width=&quot;300&quot; height=&quot;212&quot; /&gt;&lt;/p&gt;
&lt;p&gt;Depending on the events, colors will be used to write the corresponding
information. Errors will be displayed as light red, for instance.&lt;/p&gt;    &lt;p&gt;Logging could be very handy for interactive debug of a client
application.&lt;/p&gt;
&lt;p&gt;Since our &lt;code&gt;TSynLog / TSQLLog&lt;/code&gt; class feature an optional ouput to
a console, you are able to see in real-time the incoming requests - see for
instance how &lt;code&gt;14 - Interface based servicesProject14ServerHttp.pas&lt;/code&gt;
sample is initialized:&lt;/p&gt;
&lt;pre&gt;
&lt;strong&gt;begin&lt;/strong&gt;
  &lt;em&gt;// define the log level&lt;/em&gt;
  &lt;strong&gt;with&lt;/strong&gt; TSQLLog.Family &lt;strong&gt;do begin&lt;/strong&gt;
    Level := LOG_VERBOSE;
    &lt;span style=&quot;background-color:yellow;&quot;&gt;EchoToConsole := LOG_VERBOSE; &lt;em&gt;// log all events to the console&lt;/em&gt;&lt;/span&gt;
  &lt;strong&gt;end&lt;/strong&gt;;
  &lt;em&gt;// create a Data Model&lt;/em&gt;
  aModel := TSQLModel.Create([],ROOT_NAME);
  (...)
&lt;/pre&gt;
&lt;p&gt;You can select which events are to be echoed on the console (perhaps you
expect only errors to appear, for instance).&lt;/p&gt;
&lt;p&gt;Note that this echoing process slow down the logging process a lot, since it
is currently implemented in a blocking mode, and flushes each row to the log
file. This feature is therefore disabled by default, and not to be enabled on a
production server, but only to make interactive debugging easier.&lt;/p&gt;
&lt;p&gt;Feedback is &lt;a href=&quot;http://synopse.info/forum/viewtopic.php?id=1077&quot;&gt;welcome on our forum&lt;/a&gt;.&lt;/p&gt;</description>
    
    
    
      </item>
    
  <item>
    <title>External database speed improvements</title>
    <link>http://blog.synopse.info/post/2013/01/28/External-database-speed-improvements</link>
    <guid isPermaLink="false">urn:md5:7bbbebc80b718cca3a6f16e82e7afd68</guid>
    <pubDate>Mon, 28 Jan 2013 08:16:00 +0100</pubDate>
    <dc:creator>A.Bouchez</dc:creator>
        <category>mORMot Framework</category>
        <category>array binding</category><category>Batch</category><category>blog</category><category>Database</category><category>Delphi</category><category>JSON</category><category>mORMot</category><category>MSSQL</category><category>ODBC</category><category>OleDB</category><category>Oracle</category><category>ORM</category><category>performance</category><category>Source</category><category>SQL</category><category>SQLite3</category><category>SynDB</category><category>Synopse</category>    
    <description>&lt;p&gt;Some major speed improvements have been made to our &lt;code&gt;SynDB*&lt;/code&gt;
units, and how they are used within the &lt;em&gt;mORMot&lt;/em&gt; persistence
layer.&lt;br /&gt;
It results in an amazing speed increase, in some cases.&lt;/p&gt;
&lt;p&gt;Here are some of the optimizations how took place in the source code
trunk:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;SQL statement &lt;a href=&quot;http://synopse.info/forum/viewtopic.php?pid=6359#p6359&quot;&gt;client-side cache in
ODBC and OleDB&lt;/a&gt;;&lt;/li&gt;
&lt;li&gt;SQL statement &lt;a href=&quot;http://docs.oracle.com/cd/B28359_01/appdev.111/b28395/oci09adv.htm#i471377&quot;&gt;server-side
cache for Oracle&lt;/a&gt;;&lt;/li&gt;
&lt;li&gt;When inserting individual data rows in an external table, the last inserted
IDs are maintained in memory instead of executing &amp;quot;&lt;em&gt;select max(id)&lt;/em&gt;&amp;quot; -
 we added a new property &lt;code&gt;EngineAddUseSelectMaxID&lt;/code&gt; to unset
this optimization - we noted that this modification circumvented a &lt;a href=&quot;http://www.firebirdfaq.org/faq205/&quot;&gt;known limitation of Firebird&lt;/a&gt; very
efficiently.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Overall, I observed from x2 to x10 performance boost with simple
&lt;code&gt;Add()&lt;/code&gt; operations, using ODBC, OleDB and direct Oracle access, when
compare to &lt;a href=&quot;http://blog.synopse.info/post/2012/09/14/Updated-mORMot-benchmarks-on-another-HW-configuration&quot;&gt;previous
benchmarks&lt;/a&gt; (which were already impressive).&lt;br /&gt;
&lt;a href=&quot;http://blog.synopse.info/post/2011/06/03/BATCH-sequences-for-adding/updating/deleting-records&quot;&gt;BATCH
mode performance&lt;/a&gt; is less impacted, since it by-passed some of those
limitations, but even in this operation mode, there is some benefits
(especially with ODBC and OleDB).&lt;/p&gt;
&lt;p&gt;Here are some results, directly generated by the supplied &amp;quot;&lt;em&gt;15 - External
DB performance&lt;/em&gt;&amp;quot; sample.&lt;/p&gt;    &lt;h3&gt;Insertion speed&lt;/h3&gt;
&lt;p&gt;Here we test insertion of some records, for most of our supplied
engines.&lt;br /&gt;
We did the test with &lt;code&gt;UNIK&lt;/code&gt; conditional undefined, i.e. with no
index of the &lt;code&gt;Name&lt;/code&gt; field.&lt;/p&gt;
&lt;p&gt;A Core i7 notebook has been used, as hardware platform.&lt;br /&gt;
Oracle 11g database is remotely accessed over a corporate network, so latency
and bandwidth is not optimal.&lt;br /&gt;
The hardrive is a SSD this time - so we will see how it affects the
results.&lt;/p&gt;
&lt;table&gt;
&lt;tbody&gt;
&lt;tr align=&quot;center&quot;&gt;
&lt;td&gt; &lt;/td&gt;
&lt;td&gt;&lt;strong&gt;SQLite3&lt;br /&gt;
(file full)&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;SQLite3&lt;br /&gt;
(file off)&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;SQLite3&lt;br /&gt;
(mem)&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;TObjectList&lt;br /&gt;
(static)&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;TObjectList&lt;br /&gt;
(virtual)&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;SQLite3&lt;br /&gt;
(ext file full)&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;SQLite3&lt;br /&gt;
(ext file off)&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;SQLite3&lt;br /&gt;
(ext mem)&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Oracle&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;ODBC Oracle&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Jet&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr align=&quot;center&quot;&gt;
&lt;td&gt;&lt;strong&gt;Direct&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;501&lt;/td&gt;
&lt;td&gt;911&lt;/td&gt;
&lt;td&gt;81870&lt;/td&gt;
&lt;td&gt;281848&lt;/td&gt;
&lt;td&gt;288234&lt;/td&gt;
&lt;td&gt;548&lt;/td&gt;
&lt;td&gt;952&lt;/td&gt;
&lt;td&gt;72697&lt;/td&gt;
&lt;td&gt;518&lt;/td&gt;
&lt;td&gt;512&lt;/td&gt;
&lt;td&gt;4159&lt;/td&gt;
&lt;/tr&gt;
&lt;tr align=&quot;center&quot;&gt;
&lt;td&gt;&lt;strong&gt;Batch&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;523&lt;/td&gt;
&lt;td&gt;891&lt;/td&gt;
&lt;td&gt;102614&lt;/td&gt;
&lt;td&gt;409836&lt;/td&gt;
&lt;td&gt;417257&lt;/td&gt;
&lt;td&gt;557&lt;/td&gt;
&lt;td&gt;868&lt;/td&gt;
&lt;td&gt;91617&lt;/td&gt;
&lt;td&gt;77155&lt;/td&gt;
&lt;td&gt;509&lt;/td&gt;
&lt;td&gt;4441&lt;/td&gt;
&lt;/tr&gt;
&lt;tr align=&quot;center&quot;&gt;
&lt;td&gt;&lt;strong&gt;Trans&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;90388&lt;/td&gt;
&lt;td&gt;95884&lt;/td&gt;
&lt;td&gt;96612&lt;/td&gt;
&lt;td&gt;279579&lt;/td&gt;
&lt;td&gt;286188&lt;/td&gt;
&lt;td&gt;99681&lt;/td&gt;
&lt;td&gt;70950&lt;/td&gt;
&lt;td&gt;105674&lt;/td&gt;
&lt;td&gt;1024&lt;/td&gt;
&lt;td&gt;1432&lt;/td&gt;
&lt;td&gt;4920&lt;/td&gt;
&lt;/tr&gt;
&lt;tr align=&quot;center&quot;&gt;
&lt;td&gt;&lt;strong&gt;Batch Trans&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;110869&lt;/td&gt;
&lt;td&gt;117376&lt;/td&gt;
&lt;td&gt;125190&lt;/td&gt;
&lt;td&gt;412813&lt;/td&gt;
&lt;td&gt;398851&lt;/td&gt;
&lt;td&gt;127424&lt;/td&gt;
&lt;td&gt;126627&lt;/td&gt;
&lt;td&gt;121368&lt;/td&gt;
&lt;td&gt;62601&lt;/td&gt;
&lt;td&gt;1019&lt;/td&gt;
&lt;td&gt;4926&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;img src=&quot;http://chart.apis.google.com/chart?chtt=Insertion+speed+%28rows%2Fsecond%29&amp;amp;chxl=1:|Batch+Trans|Trans|Batch|Direct&amp;amp;chxt=x,y&amp;amp;chbh=a&amp;amp;chs=600x300&amp;amp;cht=bhg&amp;amp;chco=3D7930,3D8930,309F30,6070F0,5070E0,40C355,65D055,80C1A2,F05050,F0A280&amp;amp;chxr=0,0,417257&amp;amp;chds=0,417257,0,417257,0,417257,0,417257,0,417257&amp;amp;chd=t:501,523,90388,110869|911,891,95884,117376|81870,102614,96612,125190|281848,409836,279579,412813|288234,417257,286188,398851|548,557,99681,127424|952,868,70950,126627|72697,91617,105674,121368|518,77155,1024,62601|512,509,1432,1019|4159,4441,4920,4926&amp;amp;chdl=SQLite3+%28file+full%29|SQLite3+%28file+off%29|SQLite3+%28mem%29|TObjectList+%28static%29|TObjectList+%28virtual%29|SQLite3+%28ext+file+full%29|SQLite3+%28ext+file+off%29|SQLite3+%28ext+mem%29|Oracle|ODBC+Oracle|Jet&quot; /&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;http://chart.apis.google.com/chart?chtt=Insertion+speed+%28rows%2Fsecond%29&amp;amp;chxl=1:|Jet|ODBC+Oracle|Oracle|SQLite3+%28ext+mem%29|SQLite3+%28ext+file+off%29|SQLite3+%28ext+file+full%29|TObjectList+%28virtual%29|TObjectList+%28static%29|SQLite3+%28mem%29|SQLite3+%28file+off%29|SQLite3+%28file+full%29&amp;amp;chxt=x,y&amp;amp;chbh=a&amp;amp;chs=600x300&amp;amp;cht=bhg&amp;amp;chco=3D7930,3D8930,309F30,6070F0,5070E0,40C355,65D055,80C1A2,F05050,F0A280&amp;amp;chxr=0,0,417257&amp;amp;chds=0,417257,0,417257,0,417257,0,417257,0,417257,0,417257,0,417257,0,417257,0,417257,0,417257,0,417257&amp;amp;chd=t:501,911,81870,281848,288234,548,952,72697,518,512,4159|523,891,102614,409836,417257,557,868,91617,77155,509,4441|90388,95884,96612,279579,286188,99681,70950,105674,1024,1432,4920|110869,117376,125190,412813,398851,127424,126627,121368,62601,1019,4926&amp;amp;chdl=Direct|Batch|Trans|Batch+Trans&quot; /&gt;&lt;/p&gt;
&lt;p&gt;Performance gain is impressive, especially for &amp;quot;ODBC Oracle&amp;quot; and also &amp;quot;OleDB
Jet&amp;quot;.&lt;br /&gt;
Since Jet/MSAccess is a local engine, it is faster than Oracle for one record
retrieval - it does not suffer from the network latency. But it is faster than
&lt;em&gt;SQlite3&lt;/em&gt; at insertion, due to a multi-thread design - which is perhaps
&lt;a href=&quot;http://www.sqlite.org/atomiccommit.html&quot;&gt;less ACID&lt;/a&gt; nor &lt;a href=&quot;http://www.sqlite.org/testing.html&quot;&gt;proven&lt;/a&gt;.&lt;br /&gt;
Note that this hardware configuration run on a SSD, so even &amp;quot;SQLite3 (file
full)&amp;quot; configuration is very much boosted - about 3 times faster.&lt;br /&gt;
Our direct Oracle access classes achieve more than 77,000 inserts per second in
BATCH mode (using the Array Binding feature).&lt;br /&gt;
Direct &lt;code&gt;TObjectList&lt;/code&gt; in-memory engine reaches amazing speed, when
used in BATCH mode - more than 400,000 inserts per second!&lt;/p&gt;
&lt;h3&gt;Read speed&lt;/h3&gt;
&lt;table&gt;
&lt;tbody&gt;
&lt;tr align=&quot;center&quot;&gt;
&lt;td&gt; &lt;/td&gt;
&lt;td&gt;&lt;strong&gt;SQLite3&lt;br /&gt;
(file full)&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;SQLite3&lt;br /&gt;
(file off)&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;SQLite3&lt;br /&gt;
(mem)&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;TObjectList&lt;br /&gt;
(static)&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;TObjectList&lt;br /&gt;
(virtual)&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;SQLite3&lt;br /&gt;
(ext file full)&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;SQLite3&lt;br /&gt;
(ext file off)&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;SQLite3&lt;br /&gt;
(ext mem)&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Oracle&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;ODBC Oracle&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Jet&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr align=&quot;center&quot;&gt;
&lt;td&gt;&lt;strong&gt;By one&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;26777&lt;/td&gt;
&lt;td&gt;26933&lt;/td&gt;
&lt;td&gt;122016&lt;/td&gt;
&lt;td&gt;298400&lt;/td&gt;
&lt;td&gt;301041&lt;/td&gt;
&lt;td&gt;135413&lt;/td&gt;
&lt;td&gt;133571&lt;/td&gt;
&lt;td&gt;131877&lt;/td&gt;
&lt;td&gt;1289&lt;/td&gt;
&lt;td&gt;1156&lt;/td&gt;
&lt;td&gt;2413&lt;/td&gt;
&lt;/tr&gt;
&lt;tr align=&quot;center&quot;&gt;
&lt;td&gt;&lt;strong&gt;All Virtual&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;429331&lt;/td&gt;
&lt;td&gt;427423&lt;/td&gt;
&lt;td&gt;447227&lt;/td&gt;
&lt;td&gt;715717&lt;/td&gt;
&lt;td&gt;241289&lt;/td&gt;
&lt;td&gt;232385&lt;/td&gt;
&lt;td&gt;167420&lt;/td&gt;
&lt;td&gt;202839&lt;/td&gt;
&lt;td&gt;63473&lt;/td&gt;
&lt;td&gt;35029&lt;/td&gt;
&lt;td&gt;127772&lt;/td&gt;
&lt;/tr&gt;
&lt;tr align=&quot;center&quot;&gt;
&lt;td&gt;&lt;strong&gt;All Direct&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;443773&lt;/td&gt;
&lt;td&gt;433463&lt;/td&gt;
&lt;td&gt;427094&lt;/td&gt;
&lt;td&gt;711035&lt;/td&gt;
&lt;td&gt;700574&lt;/td&gt;
&lt;td&gt;432189&lt;/td&gt;
&lt;td&gt;334179&lt;/td&gt;
&lt;td&gt;340136&lt;/td&gt;
&lt;td&gt;90184&lt;/td&gt;
&lt;td&gt;39485&lt;/td&gt;
&lt;td&gt;186164&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;img src=&quot;http://chart.apis.google.com/chart?chtt=Read+speed+%28rows%2Fsecond%29&amp;amp;chxl=1:|All+Direct|All+Virtual|By+one&amp;amp;chxt=x,y&amp;amp;chbh=a&amp;amp;chs=600x300&amp;amp;cht=bhg&amp;amp;chco=3D7930,3D8930,309F30,6070F0,5070E0,40C355,65D055,80C1A2,F05050,F0A280&amp;amp;chxr=0,0,715717&amp;amp;chds=0,715717,0,715717,0,715717&amp;amp;chd=t:26777,429331,443773|26933,427423,433463|122016,447227,427094|298400,715717,711035|301041,241289,700574|135413,232385,432189|133571,167420,334179|131877,202839,340136|1289,63473,90184|1156,35029,39485|2413,127772,186164&amp;amp;chdl=SQLite3+%28file+full%29|SQLite3+%28file+off%29|SQLite3+%28mem%29|TObjectList+%28static%29|TObjectList+%28virtual%29|SQLite3+%28ext+file+full%29|SQLite3+%28ext+file+off%29|SQLite3+%28ext+mem%29|Oracle|ODBC+Oracle|Jet&quot; /&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;http://chart.apis.google.com/chart?chtt=Read+speed+%28rows%2Fsecond%29&amp;amp;chxl=1:|Jet|ODBC+Oracle|Oracle|SQLite3+%28ext+mem%29|SQLite3+%28ext+file+off%29|SQLite3+%28ext+file+full%29|TObjectList+%28virtual%29|TObjectList+%28static%29|SQLite3+%28mem%29|SQLite3+%28file+off%29|SQLite3+%28file+full%29&amp;amp;chxt=x,y&amp;amp;chbh=a&amp;amp;chs=600x300&amp;amp;cht=bhg&amp;amp;chco=3D7930,3D8930,309F30,6070F0,5070E0,40C355,65D055,80C1A2,F05050,F0A280&amp;amp;chxr=0,0,715717&amp;amp;chds=0,715717,0,715717,0,715717,0,715717,0,715717,0,715717,0,715717,0,715717,0,715717,0,715717,0,715717&amp;amp;chd=t:26777,26933,122016,298400,301041,135413,133571,131877,1289,1156,2413|429331,427423,447227,715717,241289,232385,167420,202839,63473,35029,127772|443773,433463,427094,711035,700574,432189,334179,340136,90184,39485,186164&amp;amp;chdl=By+one|All+Virtual|All+Direct&quot; /&gt;&lt;/p&gt;
&lt;p&gt;Reading speed was also increased. ODBC results have the biggest
improvement.&lt;br /&gt;
Server-side statement cache for Oracle makes individual reading of records 2
times faster. Wow.&lt;br /&gt;
The &lt;em&gt;SQLite3&lt;/em&gt; engine is still the more reactive SQL database here, when
it comes to reading. &lt;br /&gt;
Of course, direct &lt;code&gt;TObjectList&lt;/code&gt; engine is pretty fast - more than
700,000 records per second.&lt;/p&gt;
&lt;p&gt;Feedback is &lt;a href=&quot;http://synopse.info/forum/viewtopic.php?pid=6363#p6363&quot;&gt;welcome on our
forum&lt;/a&gt;, as usual.&lt;/p&gt;</description>
    
    
    
      </item>
    
  <item>
    <title>Video about mORMot authentication</title>
    <link>http://blog.synopse.info/post/2013/01/27/Video-about-mORMot-authentication</link>
    <guid isPermaLink="false">urn:md5:5e43b6dc36bbf9845bfc49efceaad90b</guid>
    <pubDate>Sun, 27 Jan 2013 10:13:00 +0100</pubDate>
    <dc:creator>A.Bouchez</dc:creator>
        <category>mORMot Framework</category>
        <category>AJAX</category><category>authentication</category><category>blog</category><category>DataSnap</category><category>Delphi</category><category>Documentation</category><category>GoodPractice</category><category>ORM</category><category>security</category><category>session</category>    
    <description>    &lt;p&gt;A new &lt;a href=&quot;http://synopse.info/forum/viewtopic.php?id=1060&quot;&gt;&lt;em&gt;mORMot&lt;/em&gt; user notified
on our forum&lt;/a&gt; that he just made a short video, about authentication and
security with our framework, from the perspective of an AJAX Client.&lt;br /&gt;
Many thanks for sharing your experiences!&lt;/p&gt;
&lt;p&gt;This video illustrate &lt;a href=&quot;http://blog.synopse.info/post/2011/05/24/How-to-implement-RESTful-authentication&quot;&gt;how RESTful
authentication is implemented by mORMot&lt;/a&gt;.&lt;br /&gt;
It compares also with the unsecured scheme used with
&lt;em&gt;DataSnap&lt;/em&gt; - pretty informative.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://youtu.be/LIl1HbjxnIA&quot;&gt;Click here to watch the 5 minutes
video.&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Each time you are logged, a light session is created on the server, and is
the root of all &lt;em&gt;mORMot&lt;/em&gt; advanced &lt;a href=&quot;http://blog.synopse.info/post/2012/03/07/Interface-based-services-implementation-details&quot;&gt;security
attributes&lt;/a&gt;.&lt;br /&gt;
Also a big difference with the heavy implementation of &lt;em&gt;DataSnap&lt;/em&gt;
session handling.&lt;/p&gt;
&lt;p&gt;Note that the 1.18 upcoming revision feature Windows Authentication, i.e.
&lt;a href=&quot;http://blog.synopse.info/post/2012/11/20/Authentication-using-Windows-credentials&quot;&gt;automatic
log with your Windows credentials.&lt;/a&gt;&lt;br /&gt;
With it, it is not even necessary to enter/remember/manage your login/password
pair: &lt;em&gt;mORMot&lt;/em&gt; is able to use your Windows domain security to let you
connected.&lt;/p&gt;
&lt;p&gt;Feedback &lt;a href=&quot;http://synopse.info/forum/viewtopic.php?id=1060&quot;&gt;is
welcome on our forum&lt;/a&gt;.&lt;/p&gt;</description>
    
    
    
      </item>
    
</channel>
</rss>