Custom Memory Allocator – Arma 2

From Bohemia Interactive Community
Jump to navigation Jump to search
m (Moved "see also" note to {{Hatnote}})
m (Text replacement - "\[ *((ftp|http)s?:\/\/[^ ]+) +([^ =]+) *\]" to "{{Link|$1|$3}}")
 
(15 intermediate revisions by 4 users not shown)
Line 1: Line 1:
{{Hatnote|This page is about Arma 2 functionality. For similar functionality in Arma 3, see [[Arma 3: Custom Memory Allocator]].}}
{{TOC|side}}
Since Arma 2 Operation Arrowhead build 85869 (1.60 beta) it is possible to provide custom memory allocators for the game. <br>
{{Feature|arma3|This page is about {{arma2}} functionality. For similar functionality in {{arma3}}, see [[Arma 3: Custom Memory Allocator]].}}
The memory allocator is a very important component, which significantly affects both performance an stability of the game. <br>  
 
The purpose of this customization is to allow the allocator to be developed independently on the application, <br>
Since {{arma2oa}} build 85869 (1.60 beta) it is possible to provide custom memory allocators for the game.<br>
The memory allocator is a very important component, which significantly affects both performance an stability of the game.<br>  
The purpose of this customization is to allow the allocator to be developed independently on the application,<br>
allowing both [[Bohemia Interactive]] and community to fix bugs and improve performance without having to modify the core game files.
allowing both [[Bohemia Interactive]] and community to fix bugs and improve performance without having to modify the core game files.


==Default==


Default allocator used by engine until build 1.60.87645 is based on Intel TBB 3 (see details about <b>tbb3malloc_bi</b> below)<br>
== Default ==
Default allocator used by engine after build 1.60.87645 is based on Intel TBB 4 (see details about <b>tbb4malloc_bi</b> below)


==Specifying a custom allocator==
Default allocator used by engine until build 1.60.87645 is based on Intel TBB 3 (see details about '''tbb3malloc_bi''' below)<br>
Default allocator used by engine after build 1.60.87645 is based on Intel TBB 4 (see details about '''tbb4malloc_bi''' below)
 
 
== Specifying a custom allocator ==


The allocator is a dll placed in a directory named "dll" located next to the game executable. Allocator search order is:
The allocator is a dll placed in a directory named "dll" located next to the game executable. Allocator search order is:


* tbb3malloc_bi - based on [http://threadingbuildingblocks.org/ver.php?fid=171 Intel TBB 3], distributed under [http://www.gnu.org/licenses/gpl-2.0.html GPL v2] + [http://gcc.gnu.org/onlinedocs/libstdc++/manual/bk01pt01ch01s02.html RE] ([http://downloads.bistudio.com/arma2.com/update/Allocs/TBB3_source.7z source code]), based on [http://threadingbuildingblocks.org/ver.php?fid=171 tbb30_20110427oss]
* tbb3malloc_bi - based on [http://threadingbuildingblocks.org/ver.php?fid{{=}}171 Intel TBB 3], distributed under {{Link|http://www.gnu.org/licenses/gpl-2.0.html|GPL v2}} + {{Link|http://gcc.gnu.org/onlinedocs/libstdc++/manual/bk01pt01ch01s02.html|RE}} ({{Link|link= http://downloads.bistudio.com/arma2.com/update/Allocs/TBB3_source.7z|text= source code}}), based on {{Link|http://threadingbuildingblocks.org/ver.php?fid{{=}}171|tbb30_20110427oss}}
* tbb4malloc_bi - based on [http://threadingbuildingblocks.org/ver.php?fid=176 Intel TBB 4], distributed under [http://www.gnu.org/licenses/gpl-2.0.html GPL v2] + [http://gcc.gnu.org/onlinedocs/libstdc++/manual/bk01pt01ch01s02.html RE] ([http://downloads.bistudio.com/arma2.com/update/Allocs/TBB4_source.7z source code]) based on [http://threadingbuildingblocks.org/ver.php?fid=185 tbb40_20120408oss]
* tbb4malloc_bi - based on [http://threadingbuildingblocks.org/ver.php?fid{{=}}176 Intel TBB 4], distributed under {{Link|http://www.gnu.org/licenses/gpl-2.0.html|GPL v2}} + {{Link|http://gcc.gnu.org/onlinedocs/libstdc++/manual/bk01pt01ch01s02.html|RE}} ({{Link|link= http://downloads.bistudio.com/arma3.com/allocs/TBB4_source_43u2.7z|text= source code}}) based on {{Link|https://www.threadingbuildingblocks.org/download#stable-releases|tbb43_20141204oss}}
* jemalloc_bi - based on [http://www.canonware.com/download/jemalloc/ JEMalloc], distributed under [http://www.canonware.com/jemalloc/license.html BSD-derived license] ([http://downloads.bistudio.com/arma2.com/update/Allocs/JEMalloc_source.7z source code])
* jemalloc_bi - based on {{Link|http://www.canonware.com/download/jemalloc/|JEMalloc}}, distributed under {{Link|http://www.canonware.com/jemalloc/license.html|BSD-derived license}} ({{Link|link= http://downloads.bistudio.com/arma2.com/update/Allocs/JEMalloc_source.7z|text= source code}})
* tcmalloc_bi - based on [http://code.google.com/p/google-perftools/ TCMalloc], distributed under [http://www.opensource.org/licenses/bsd-license.php New BSD license] ([http://downloads.bistudio.com/arma2.com/update/Allocs/TCMalloc_source.7z source code]) based on [http://google-perftools.googlecode.com/svn/trunk/src/ revision 100]
* tcmalloc_bi - based on {{Link|http://code.google.com/p/google-perftools/|TCMalloc}}, distributed under {{Link|http://www.opensource.org/licenses/bsd-license.php|New BSD license}} ({{Link|link= http://downloads.bistudio.com/arma2.com/update/Allocs/TCMalloc_source.7z|text= source code}}) based on {{Link|http://google-perftools.googlecode.com/svn/trunk/src/|revision 100}}
* nedmalloc_bi - based on [http://www.nedprod.com/programs/portable/nedmalloc/ NedMalloc], distributed under [http://www.boost.org/users/license.html Boost Software License] ([http://downloads.bistudio.com/arma2.com/update/Allocs/NedMalloc_source.7z source code])
* nedmalloc_bi - based on {{Link|http://www.nedprod.com/programs/portable/nedmalloc/|NedMalloc}}, distributed under {{Link|http://www.boost.org/users/license.html|Boost Software License}} ({{Link|link= http://downloads.bistudio.com/arma2.com/update/Allocs/NedMalloc_source.7z|text= source code}})
* customMalloc_bi - not provided, feel free to plug-in your own
* customMalloc_bi - not provided, feel free to plug-in your own


If no allocator dll is found, functions _aligned_malloc/ _aligned_free (using Windows Heap functions) are used as a fallback <br>
If no allocator dll is found, functions _aligned_malloc/ _aligned_free (using Windows Heap functions) are used as a fallback.
<i>note: Windows 7 allocator seems to be quite good, and it may therefore make sense for some users to delete all custom allocators on Windows 7 or newer).</i>
{{Feature|informative|The Windows 7 allocator seems to be quite good, and it may therefore make sense for some users to delete all custom allocators on Windows 7 or newer.}}


You can select an allocator by via '''commandline''' below or ''deleting other allocators'' from the \dll\ folder.
You can select an allocator by via '''commandline''' below or ''deleting other allocators'' from the \dll\ folder.


===Commandline parameter===
=== Commandline parameter ===


You can specify a particular allocator from a command line, like: <br>
You can specify a particular allocator from a command line, like: <br>
*<b>-malloc=tbb3malloc_bi</b>  <br>
* -malloc=tbb3malloc_bi
*<b>-malloc=tbb4malloc_bi</b>  <br>
* -malloc=tbb4malloc_bi
*<b>-malloc=jemalloc_bi</b>  <br>
* -malloc=jemalloc_bi
*<b>-malloc=tcmalloc_bi</b>  <br>
* -malloc=tcmalloc_bi
*<b>-malloc=nedmalloc_bi</b>  <br>
* -malloc=nedmalloc_bi
or <br>
or
*<b>-malloc=mybestmalloc_bi</b> <br>
* -malloc=mybestmalloc_bi
*<b>-malloc=system</b> <i>can be used to force using Windows allocator even when allocator dlls are present </i><br>
* -malloc=system ''can be used to force using Windows allocator even when allocator dlls are present''
<i>(dll directory and extension are appended automatically, the allocator must not be located in other directory and its name must not contain any dots before the .dll extension)</i>
{{Feature|informative|Dll directory and extension are appended automatically, the allocator must not be located in other directory and its name must not contain any dots before the .dll extension.}}


===Dedicated server===
=== Dedicated server ===


You can specify allocator for Windows dedicated server the same way as for client binary, but expected performance gain is minimal, because of low concurrency of the dedicated server code compared to a client.
You can specify allocator for Windows dedicated server the same way as for client binary, but expected performance gain is minimal, because of low concurrency of the dedicated server code compared to a client.
Line 45: Line 49:
Linux server uses allocator provided by operating system. <i>There are NO plans to allow its customization</i>.
Linux server uses allocator provided by operating system. <i>There are NO plans to allow its customization</i>.


==DLL Interface==
== DLL Interface ==
The dll interface is as follows:
The dll interface is as follows:


<syntaxhighlight lang="cpp">extern "C" {
<syntaxhighlight lang="cpp">
  __declspec(dllexport) size_t __stdcall MemTotalCommitted();         // _MemTotalCommitted@0
extern "C" {
  __declspec(dllexport) size_t __stdcall MemTotalReserved();         // _MemTotalReserved@0
__declspec(dllexport) size_t __stdcall MemTotalCommitted(); // _MemTotalCommitted@0
  __declspec(dllexport) size_t __stdcall MemFlushCache(size_t size); // _MemFlushCache@4
__declspec(dllexport) size_t __stdcall MemTotalReserved(); // _MemTotalReserved@0
  __declspec(dllexport) void __stdcall MemFlushCacheAll();           // _MemFlushCacheAll@0
__declspec(dllexport) size_t __stdcall MemFlushCache(size_t size); // _MemFlushCache@4
  __declspec(dllexport) size_t __stdcall MemSize(void *mem);         // _MemSize@4
__declspec(dllexport) void __stdcall MemFlushCacheAll(); // _MemFlushCacheAll@0
  __declspec(dllexport) void *__stdcall MemAlloc(size_t size);       // _MemAlloc@4
__declspec(dllexport) size_t __stdcall MemSize(void *mem); // _MemSize@4
  __declspec(dllexport) void __stdcall MemFree(void *mem);           // _MemFree@4
__declspec(dllexport) void *__stdcall MemAlloc(size_t size); // _MemAlloc@4
__declspec(dllexport) void __stdcall MemFree(void *mem); // _MemFree@4
};
};
</syntaxhighlight>
</syntaxhighlight>


Note: besides of the interface above, if the allocator is performing any per-thread caching, it will typically want to perform a cleanup of per-thread data on DLL_THREAD_DETACH event sent to [http://msdn.microsoft.com/en-us/library/windows/desktop/ms682583(v=vs.85).aspx DllMain function].
Note: besides of the interface above, if the allocator is performing any per-thread caching, it will typically want to perform a cleanup of per-thread data on DLL_THREAD_DETACH event sent to [http://msdn.microsoft.com/en-us/library/windows/desktop/ms682583(v{{=}}vs.85).aspx DllMain function].


===  MemTotalCommitted() ===
===  MemTotalCommitted() ===
Total memory committed by the allocator (should correspond to VirtualAlloc with MEM_COMMIT)
Total memory committed by the allocator (should correspond to VirtualAlloc with MEM_COMMIT)


===  MemTotalReserved() ===
===  MemTotalReserved() ===
Total memory reserved by the allocator (should correspond to VirtualAlloc with MEM_RESERVE)
Total memory reserved by the allocator (should correspond to VirtualAlloc with MEM_RESERVE)


===  MemFlushCache(size_t size) ===
===  MemFlushCache(size_t size) ===
Try to flush at least "size" bytes of memory from caches and working areas, return how much memory was flushed. Called by game when memory needs to be trimmed to reduce virtual memory use.
Try to flush at least "size" bytes of memory from caches and working areas, return how much memory was flushed. Called by game when memory needs to be trimmed to reduce virtual memory use.


===  MemFlushCacheAll() ===
===  MemFlushCacheAll() ===
Flush all memory held in caches and working areas. Called by game when memory needs to be trimmed to reduce virtual memory use.
Flush all memory held in caches and working areas. Called by game when memory needs to be trimmed to reduce virtual memory use.


===  MemSize(void *mem) ===
===  MemSize(void *mem) ===
Return allocated size of given memory block.
Return allocated size of given memory block.


===  MemAlloc(size_t size) ===
===  MemAlloc(size_t size) ===
Allocate at least size bytes of memory, return the allocated memory. If the size is 16 B or more, the memory must be 16 B -aligned, so that it is usable to hold SSE data.
Allocate at least size bytes of memory, return the allocated memory. If the size is 16 B or more, the memory must be 16 B -aligned, so that it is usable to hold SSE data.


===  MemFree(void *mem) ===
===  MemFree(void *mem) ===
Free given memory block.
Free given memory block.


<!-- Categories -->


[[Category:Arma 2]]
[[Category:Arma 2: Editing]]
[[Category:Startup Parameters]]
[[Category:Startup Parameters]]

Latest revision as of 17:42, 28 April 2023

Arma 3
This page is about Arma 2 functionality. For similar functionality in Arma 3, see Arma 3: Custom Memory Allocator.

Since Arma 2: Operation Arrowhead build 85869 (1.60 beta) it is possible to provide custom memory allocators for the game.
The memory allocator is a very important component, which significantly affects both performance an stability of the game.
The purpose of this customization is to allow the allocator to be developed independently on the application,
allowing both Bohemia Interactive and community to fix bugs and improve performance without having to modify the core game files.


Default

Default allocator used by engine until build 1.60.87645 is based on Intel TBB 3 (see details about tbb3malloc_bi below)
Default allocator used by engine after build 1.60.87645 is based on Intel TBB 4 (see details about tbb4malloc_bi below)


Specifying a custom allocator

The allocator is a dll placed in a directory named "dll" located next to the game executable. Allocator search order is:

If no allocator dll is found, functions _aligned_malloc/ _aligned_free (using Windows Heap functions) are used as a fallback.

The Windows 7 allocator seems to be quite good, and it may therefore make sense for some users to delete all custom allocators on Windows 7 or newer.

You can select an allocator by via commandline below or deleting other allocators from the \dll\ folder.

Commandline parameter

You can specify a particular allocator from a command line, like:

  • -malloc=tbb3malloc_bi
  • -malloc=tbb4malloc_bi
  • -malloc=jemalloc_bi
  • -malloc=tcmalloc_bi
  • -malloc=nedmalloc_bi

or

  • -malloc=mybestmalloc_bi
  • -malloc=system can be used to force using Windows allocator even when allocator dlls are present
Dll directory and extension are appended automatically, the allocator must not be located in other directory and its name must not contain any dots before the .dll extension.

Dedicated server

You can specify allocator for Windows dedicated server the same way as for client binary, but expected performance gain is minimal, because of low concurrency of the dedicated server code compared to a client.

Linux server uses allocator provided by operating system. There are NO plans to allow its customization.

DLL Interface

The dll interface is as follows:

extern "C" {
	__declspec(dllexport) size_t __stdcall MemTotalCommitted();			// _MemTotalCommitted@0
	__declspec(dllexport) size_t __stdcall MemTotalReserved();			// _MemTotalReserved@0
	__declspec(dllexport) size_t __stdcall MemFlushCache(size_t size);	// _MemFlushCache@4
	__declspec(dllexport) void __stdcall MemFlushCacheAll();			// _MemFlushCacheAll@0
	__declspec(dllexport) size_t __stdcall MemSize(void *mem);			// _MemSize@4
	__declspec(dllexport) void *__stdcall MemAlloc(size_t size);		// _MemAlloc@4
	__declspec(dllexport) void __stdcall MemFree(void *mem);			// _MemFree@4
};

Note: besides of the interface above, if the allocator is performing any per-thread caching, it will typically want to perform a cleanup of per-thread data on DLL_THREAD_DETACH event sent to DllMain function.

MemTotalCommitted()

Total memory committed by the allocator (should correspond to VirtualAlloc with MEM_COMMIT)

MemTotalReserved()

Total memory reserved by the allocator (should correspond to VirtualAlloc with MEM_RESERVE)

MemFlushCache(size_t size)

Try to flush at least "size" bytes of memory from caches and working areas, return how much memory was flushed. Called by game when memory needs to be trimmed to reduce virtual memory use.

MemFlushCacheAll()

Flush all memory held in caches and working areas. Called by game when memory needs to be trimmed to reduce virtual memory use.

MemSize(void *mem)

Return allocated size of given memory block.

MemAlloc(size_t size)

Allocate at least size bytes of memory, return the allocated memory. If the size is 16 B or more, the memory must be 16 B -aligned, so that it is usable to hold SSE data.

MemFree(void *mem)

Free given memory block.