using System.Collections.Generic;
using System.Diagnostics;
using System.Runtime.InteropServices;
public static Poco CreatePoco(int i)
static void TestArray(int elementsCount)
Console.WriteLine("Array");
var stopwatch = new Stopwatch();
var array = new Poco[elementsCount];
for (int i = 0; i < elementsCount; ++i)
var poco = CreatePoco(i);
Console.WriteLine("Insertion time: " + stopwatch.ElapsedMilliseconds);
for (int i = 0; i < elementsCount; ++i)
Console.WriteLine("Sum: " + sum);
Console.WriteLine("Calculation time: " + stopwatch.ElapsedMilliseconds);
static void TestList(int elementsCount)
Console.WriteLine("List");
var stopwatch = new Stopwatch();
var normalList = new List<Poco>(elementsCount);
for (int i = 0; i < elementsCount; ++i)
var poco = CreatePoco(i);
Console.WriteLine("Insertion time: " + stopwatch.ElapsedMilliseconds);
for (int i = 0; i < elementsCount; ++i)
var poco = normalList[i];
Console.WriteLine("Sum: " + sum);
Console.WriteLine("Calculation time: " + stopwatch.ElapsedMilliseconds);
static void TestSafeList(int elementsCount)
Console.WriteLine("SafeList");
var stopwatch = new Stopwatch();
var safeList = new SafeList<Poco>(elementsCount, 18);
for (int i = 0; i < elementsCount; ++i)
var poco = CreatePoco(i);
Console.WriteLine("Insertion time: " + stopwatch.ElapsedMilliseconds);
for (int i = 0; i < elementsCount; ++i)
var poco = safeList.Get(i);
Console.WriteLine("Sum: " + sum);
Console.WriteLine("Calculation time: " + stopwatch.ElapsedMilliseconds);
public static void Main()
var elementsCount = 100 * 1000;
Console.WriteLine("------------------------");
for (int i = 0; i < testsCount; ++i)
TestArray(elementsCount);
GC.WaitForPendingFinalizers();
Console.WriteLine("------------------------");
for (int i = 0; i < testsCount; ++i)
GC.WaitForPendingFinalizers();
Console.WriteLine("------------------------");
for (int i = 0; i < testsCount; ++i)
TestSafeList(elementsCount);
public class SafeList<T> where T : class
private readonly int _elementSize;
private int _currentIndex = -1;
private Holder<T> holder = new Holder<T>();
public SafeList(int size, int elementSize)
_elementSize = elementSize;
_storage = new int[size * _elementSize];
storageHandle = GCHandle.Alloc(_storage);
holderHandle = GCHandle.Alloc(holder);
GCHandle handle = GCHandle.Alloc(item);
var itemAddress = Marshal.ReadIntPtr(GCHandle.ToIntPtr(handle)) - 4;
for (int i = 1; i < _elementSize; ++i)
_storage[_currentIndex*_elementSize + i] = Marshal.ReadInt32(itemAddress + i * 4);
public T GetInternal(int index)
var storageAddress = Marshal.ReadIntPtr(GCHandle.ToIntPtr(storageHandle));
var holderAddress = Marshal.ReadIntPtr(GCHandle.ToIntPtr(holderHandle));
Marshal.WriteIntPtr(holderAddress, 4, storageAddress + 2 * 4 + index * _elementSize * 4 + 4);
return GetInternal(index);