Я перешёл на новый уровень игры в прятание объектов от сборщика мусора
Написал свою обёртку UnmanagedMemory над стандартным System.Runtime.InteropServices.Marshal.
AllocHGlobal /
FreeHGlobal:
void* UnmanagedMemory.
Allocate(int size);
void UnmanagedMemory.
Free(void* pointer);
И размещаю объекты в стиле Си, благо определённое подмножество языка Си является подмножеством языка C#.
Свою обёртку пришлось написать потому, что под Mono Marshal.AllocHGlobal и Marshal.FreeHGlobal работают медленнее чем у Микрософта да ещё и можно сказать, что практически не параллельные.
Теперь моя UnmanagedString реализована как структура внутри которой лежит указатель int* p. При этом p[0] - длина строки, p[1] - счётчик ссылок, а начиная с адреса (char*)p + 4 лежат буквы char (char в C# двухбайтовый).
Всё как бы lock-free, реализовано на System.Threading.Interlocked.Exchange / Increment / Decrement.
Кстати, скорости работы стандартного аллокатора System.Runtime.InteropServices.Marshal.AllocHGlobal / FreeHGlobal если его мучить в один или в десять потоков выделяя куски памяти случайного размера 1..1024 байтов:
Microsoft .Net 4.5, Windows 7, Core i7 2600K, 3.4-3.8 GHz, DDR3 1600 MHz
Thead count = 1, rate = 6’066’457 (alloc+free) / sec
Thead count = 10, rate = 28’922’333 (alloc+free) / sec
Mono 2.10.8.1 (Debian 2.10.8.1-8), Core i7 950, 3.0-3.13 GHz, DDR3 1066 MHz
Thead count = 1, rate = 3’943’747 (alloc+free) / sec
Thead count = 10, rate = 6’112’558 (alloc+free) / sec
Моя реализация под Windows работает со скоростью 28-29 миллионов в секунду во много потоков и где-то 14-16 миллионов в секунду в один-два потока.