Skip to content
Permalink
Browse files

allows SynFPCCMemAligned to use either glibc, Intel TBB or jemalloc l…

…ibraires
  • Loading branch information...
Arnaud Bouchez
Arnaud Bouchez committed Feb 19, 2019
1 parent c246ae5 commit 2e3cd2ed4b4102c9b82833a3994e72965309c4c6
Showing with 141 additions and 27 deletions.
  1. +3 −2 SynCommons.pas
  2. +13 −9 SynDprUses.inc
  3. +124 −15 SynFPCCMemAligned.pas
  4. +1 −1 SynopseCommit.inc
@@ -120,8 +120,9 @@ interface
{$ifdef FPC}
{$ifdef FPC_FASTMM4}+' FMM4'{$else}
{$ifdef FPC_SYNTBB}+' TBB'{$else}
{$ifdef FPC_SYNCMEM}+' SCMEM'{$else}
{$ifdef FPC_CMEM}+' CMEM'{$endif}{$endif}{$endif}{$endif}
{$ifdef FPC_SYNJEMALLOC}+' JEM'{$else}
{$ifdef FPC_SYNCMEM}+' SCMEM'{$else}
{$ifdef FPC_CMEM}+' CMEM'{$endif}{$endif}{$endif}{$endif}{$endif}
{$else}
{$ifdef LVCL}+' LVCL'{$else}
{$ifdef ENHANCEDRTL}+' ERTL'{$endif}{$endif}
@@ -4,17 +4,21 @@
FastMM4Messages in '..\RTL7\FastMM4Messages.pas',
FastMM4 in '..\RTL7\FastMM4.pas',
{$else}
{$ifdef FPC_SYNTBB}
SynTBB, // you may also set FPC_NO_DEFAULT_MEMORYMANAGER
{$ifdef FPC_SYNJEMALLOC}
SynFPCCMemAligned, // after "apt-get install libjemalloc1"
{$else}
{$ifdef FPC_SYNCMEM}
SynFPCCMemAligned, // you may also set FPC_NO_DEFAULT_MEMORYMANAGER
{$ifdef FPC_SYNTBB}
SynFPCCMemAligned, // after "apt-get install libtbb2"
{$else}
{$ifdef FPC_CMEM}
cmem, // you may also set FPC_NO_DEFAULT_MEMORYMANAGER
{$endif FPC_CMEM}
{$endif FPC_SYNCMEM}
{$endif FPC_SYNTBB}
{$ifdef FPC_SYNCMEM}
SynFPCCMemAligned, // you may also set FPC_NO_DEFAULT_MEMORYMANAGER
{$else}
{$ifdef FPC_CMEM}
cmem, // you may also set FPC_NO_DEFAULT_MEMORYMANAGER
{$endif FPC_CMEM}
{$endif FPC_SYNCMEM}
{$endif FPC_SYNTBB}
{$endif FPC_SYNJEMALLOC}
{$endif FPC_FASTMM4}
{$ifdef Unix} // we may also be on Darwin / OSX
cthreads, // if you use threads: always needed for servers
@@ -1,5 +1,7 @@
/// implements a Linux FPC heap manager that uses glibc, with no overhead
// - expected to be enabled with -dFPC_NO_DEFAULT_MEMORYMANAGER -dFPC_SYNCMEM
/// implements a Linux FPC heap manager that uses external glibc, Intel TBB or
// jemalloc libraries, with no overhead
// - define -dFPC_SYNCMEM (for glibc), -dFPC_SYNTBB (after "apt-get install libtbb2")
// or -dFPC_SYNJEMALLOC (after "apt-get install libjemalloc1")
// - with Linux glibc, alignment is 2*SizeOf(pointer) i.e. 16 bytes under x86_64
unit SynFPCCMemAligned;

@@ -51,33 +53,87 @@
}

(*
Usage:
- for glibc, define -dFPC_NO_DEFAULT_MEMORYMANAGER -dFPC_SYNCMEM
- for Intel TBB, define -dFPC_SYNTBB - after "apt-get install libtbb2"
- for jemalloc, define -dFPC_SYNJEMALLOC - after "apt-get install libjemalloc1"
- and ensure your dpr/lpr start with:
uses
{$I SynDprUses.inc} // includes this unit
SynCommons, ....
or at least this SynFPCCMemAligned unit is the very first in the uses list
Some raw numbers, from TestSQL3 string allocation tests (single threaded):
- FPC default heap
500000 interning 8 KB in 77.34ms i.e. 6,464,959/s, aver. 0us, 98.6 MB/s
500000 direct 7.6 MB in 100.73ms i.e. 4,963,518/s, aver. 0us, 75.7 MB/s
- glibc 2.23
500000 interning 8 KB in 76.06ms i.e. 6,573,152/s, aver. 0us, 100.2 MB/s
500000 direct 7.6 MB in 36.64ms i.e. 13,645,915/s, aver. 0us, 208.2 MB/s
- jemalloc 3.6
500000 interning 8 KB in 78.60ms i.e. 6,361,323/s, aver. 0us, 97 MB/s
500000 direct 7.6 MB in 58.08ms i.e. 8,608,667/s, aver. 0us, 131.3 MB/s
- Intel TBB 4.4
500000 interning 8 KB in 61.96ms i.e. 8,068,810/s, aver. 0us, 123.1 MB/s
500000 direct 7.6 MB in 36.46ms i.e. 13,711,402/s, aver. 0us, 209.2 MB/s
for multi-threaded process, we observed best scaling with TBB on this system
*)

interface

{$I Synopse.inc} // set proper flags, and define LINUX for BSD and ANDROID

{$ifndef FPC}
THIS UNIT IS FOR FPC ONLY !
{$endif FPC}
{$ifndef LINUXNOTBSD}
THIS UNIT IS FOR FPC/LINUX ONLY !
- requires malloc_usable_size() -> use regular cmem unit instead
{$endif LINUXNOTBSD}

{$ifdef FPC_SYNCMEM}
{$ifndef LINUXNOTBSD}
THIS UNIT IS FOR FPC/LINUX ONLY !
- requires malloc_usable_size() -> use regular cmem unit instead
{$endif LINUXNOTBSD}
{$endif FPC_SYNCMEM}


implementation

{$ifdef FPC_SYNCMEM}

// low-level direct calls to the external glibc library

function malloc(size: PtrUInt): pointer; cdecl; external 'c' name 'malloc';
function calloc(count, size: PtrUInt): pointer; cdecl; external 'c' name 'calloc';
procedure free(p: pointer); cdecl; external 'c' name 'free';
function realloc(p: pointer; size: PtrUInt): pointer; cdecl; external 'c' name 'realloc';

function malloc_usable_size(p: pointer): PtrUInt; cdecl; external 'c' name 'malloc_usable_size';
function msize(p: pointer): PtrUInt; cdecl; external 'c' name 'malloc_usable_size';
// function missing on some platforms, so this unit is enabled only for LINUXNOTBSD
// see https://www.gnu.org/software/gnulib/manual/html_node/malloc_005fusable_005fsize.html
// = Mac OS X 10.5, FreeBSD 6.0, NetBSD 5.0, OpenBSD 3.8, Minix 3.1.8, AIX 5.1, HP-UX 11.00,
// IRIX 6.5, OSF/1 5.1, Solaris 11.3, mingw, MSVC 14, Interix 3.5, BeOS, Android 4.1

{$else}

uses
{$ifdef LINUXNOTBSD}
cthreads, // as required by libraries - will also link needed glibc
{$endif LINUXNOTBSD}
dl;

// late-binding API calls to the external malloc libraries

var
malloc: function(size: PtrUInt): pointer; cdecl;
calloc: function(count, size: PtrUInt): pointer; cdecl;
free: procedure(p: pointer); cdecl;
realloc: function(p: pointer; size: PtrUInt): pointer; cdecl;
msize: function(p: pointer): PtrUInt; cdecl;

{$endif FPC_SYNCMEM}

// TMemoryManager replacement

function _GetMem(size: PtrUInt): pointer;
@@ -111,7 +167,7 @@ function _ReAllocMem(var p: pointer; size: PtrUInt): pointer;

function _MemSize(p: pointer): PtrUInt;
begin // AFAIK used only by fpc_AnsiStr_SetLength() in RTL
result := malloc_usable_size(p);
result := msize(p);
end;

function _GetHeapStatus: THeapStatus;
@@ -125,14 +181,14 @@ function _GetFPCHeapStatus: TFPCHeapStatus;
end;

const
NewMM: TMemoryManager = ( // direct call is possible under x86_64 = no cdecl
NewMM: TMemoryManager = (
NeedLock: false;
GetMem: @{$ifdef CPUX64}malloc{$else}_Getmem{$endif};
FreeMem: @{$ifdef CPUX64}free{$else}_FreeMem{$endif};
GetMem: @_Getmem;
FreeMem: @_FreeMem;
FreememSize: @_FreememSize;
AllocMem: @_AllocMem;
ReallocMem: @_ReAllocMem;
MemSize: @{$ifdef CPUX64}malloc_usable_size{$else}_MemSize{$endif};
MemSize: @_MemSize;
InitThread: nil;
DoneThread: nil;
RelocateHeap: nil;
@@ -141,12 +197,65 @@ function _GetFPCHeapStatus: TFPCHeapStatus;

var
OldMM: TMemoryManager;
{$ifndef FPC_SYNCMEM}
lib: pointer;
{$endif FPC_SYNCMEM}

{$I-}
procedure InitMM;
begin
{$ifdef FPC_SYNCMEM}
//writeln('using glibc');
{$else}
{$ifdef FPC_SYNJEMALLOC} // jemalloc 3.6 seems slower, but maybe less fragmented
lib := dlopen('libjemalloc.so.1', RTLD_LAZY);
if lib <> nil then begin
pointer(@malloc) := dlsym(lib, 'malloc');
pointer(@calloc) := dlsym(lib, 'calloc');
pointer(@free) := dlsym(lib, 'free');
pointer(@realloc) := dlsym(lib, 'realloc');
pointer(@msize) := dlsym(lib, 'malloc_usable_size');
//writeln('using jemalloc');
end else
writeln(StdErr, dlerror, ' [apt-get install libjemalloc1]');
{$else}
lib := dlopen('libtbbmalloc.so.2', RTLD_LAZY);
if lib = nil then
lib := dlopen('libtbbmalloc.so', RTLD_LAZY);
if lib = nil then
writeln(StdErr, dlerror, ' [apt-get install libtbb2]')
else begin
pointer(@malloc) := dlsym(lib, 'scalable_malloc');
pointer(@calloc) := dlsym(lib, 'scalable_calloc');
pointer(@free) := dlsym(lib, 'scalable_free');
pointer(@realloc) := dlsym(lib, 'scalable_realloc');
pointer(@msize) := dlsym(lib, 'scalable_msize');
//writeln('using Intel TBB');
end;
{$endif FPC_SYNJEMALLOC}
{$endif FPC_SYNCMEM}
if pointer(@msize) <> nil then begin
{$ifdef CPUX64} // no cdecl on x86_64 -> direct call is just fine
NewMM.GetMem := pointer(@malloc);
NewMM.FreeMem := pointer(@free);
NewMM.MemSize := pointer(@msize);
{$endif}
GetMemoryManager(OldMM);
SetMemoryManager(NewMM);
end;
end;
{$I+}

initialization
GetMemoryManager(OldMM);
SetMemoryManager(NewMM);
InitMM;

finalization
SetMemoryManager(OldMM);
if pointer(@msize) <> nil then begin
SetMemoryManager(OldMM);
{$ifndef FPC_SYNCMEM}
if lib <> nil then
dlclose(lib);
{$endif FPC_SYNCMEM}
end;
end.

@@ -1 +1 @@
'1.18.5045'
'1.18.5046'

0 comments on commit 2e3cd2e

Please sign in to comment.
You can’t perform that action at this time.