Faster WideString process for good old non Unicode Delphi 6-2007
For pre-Unicode versions of Delphi, the unique way of having UTF-16 native
type is to use the
This type, under Windows, matched the BSTR managed type, as used by OLE and COM components.
WideString implementation calls directly the
corresponding Windows API, and do not use the main Delphi heap manager.
Even if since Vista, this API did have a huge speed-up, it is still in practice much slower than the regular
string type. Problems is not about
UTF-16 encoding, but about the memory allocation, which is shared among
processes, using the Windows global heap, and is much slower than our beloved
Newer versions of Delphi (since Delphi 2009) feature a refactored
UnicodeString type, which relies on
FastMM4 and not the Windows API, and is much faster than
Within our mORMot framework,
we by-passed this limitation by using our
RawUTF8 type, which is
UTF-8 encoded, so as Unicode ready as the new
and pretty fast.
In a recent internal project, we had to use a lot of
WideString instances, to support UTF-16 encoding in Delphi
7/2007, involving a lot of text.
It sounded to be very slow, so we had to do something!
This is where our new SynFastWideString unit comes in.
Purpose of this unit is to patch the
system.pas unit for older
versions of Delphi, so that
WideString memory allocation would use
FastMM4 instead of the slow BSTR Windows API.
It will speed up the
WideString process a lot, especially when a
lot of content is allocated, since FastMM4 is much more aggressive
than Windows' global heap and the BSTR slow API. It could be more than 50 times
faster, especially when releasing the used memory.
WideString implementation pattern does NOT feature Copy-On-Write, so is still
slower than the
string UnicodeString type as implemented since
Delphi 2009. This is the reason why this unit won't do anything on
Unicode versions of the compiler, since the new string type is to be
How to use
Just add the unit at the TOP of your
.dpr uses clause, just
after FastMM4 (if you use it, and you should!) i.e. before all other
units used by your program.
It should be initialized before any
Then the patch will be applied at runtime.
Nothing to recompile!
USING THIS UNIT MAY BREAK COMPATIBILITY WITH OLE/COM LIBRARIES !
You won't be able to retrieve and
WideString/BSTR variables from an OleDB / ADO
database provider, or any COM object.
Do not use this unit if you are calling such external call!
In practice, if you only send some BSTR content to the provider
(e.g. if you use our
SynOleDB unit without stored procedure call,
or if you use
TWideStringField for most
classes), it will work. As far as we tested.
You would have issues if you retrieve a BSTR from the COM object, or expect the COM object to change the BSTR size, e.g. with a
var WideString parameter or a COM method returning a
The following method should work, since it is using a
WideString as input parameter:
_Catalog = interface(IDispatch)
function Create(const ConnectString: WideString): OleVariant; safecall;
WideStringvalue, which will fail to be released by our SynFastWideString unit, since it is a true BSTR instance allocated by the COM library, and not an
AnsiStringallocated via FastMM4:
_Catalog = interface(IDispatch)
function GetObjectOwner(const ObjectName: WideString; ObjectType: OleVariant;
ObjectTypeId: OleVariant): WideString; safecall;
In this case, you could use the
WideStringFree() procedure, as
defined in the SynFastWideString unit, to release such an
This unit is for educational purpose only, and/or if you are 100% sure that
your code will stay self-contained, under Delphi 7 or Delphi 2007, and need use
WideString instead of
YOU HAVE BEEN WARNED - USE AT YOUR OWN RISK !