using System.Collections.Generic;
using System.Collections.Immutable;
using System.Threading.Tasks;
using System.Diagnostics;
private const int ReRuns = 5;
private static readonly Type ListType = typeof(SortedList<OrderDataBigIntegerKey, OrderDataBigInteger>);
private static readonly FieldInfo KeysFieldInfo = ListType.GetField("keys", BindingFlags.Instance | BindingFlags.NonPublic) ?? throw new NullReferenceException("keys not found");
private static readonly FieldInfo ValuesFieldInfo = ListType.GetField("values", BindingFlags.Instance | BindingFlags.NonPublic) ?? throw new NullReferenceException("values not found");
private static readonly FieldInfo SizeFieldInfo = ListType.GetField("_size", BindingFlags.Instance | BindingFlags.NonPublic) ?? throw new NullReferenceException("_size not found");
private static OrderDataBigInteger[] _prefillArray = [];
public static void Main()
A_Static_Global_Setup(50_000, 2_000);
var sl = new SortedList<OrderDataBigIntegerKey, OrderDataBigInteger>[ReRuns];
A_Iteration_Initialize(ReRuns, sl);
GC.WaitForPendingFinalizers();
var isd = new ImmutableSortedDictionary<OrderDataBigIntegerKey, OrderDataBigInteger>[ReRuns];
A_Iteration_Initialize(ReRuns, isd);
GC.WaitForPendingFinalizers();
var sd = new SortedDictionary<OrderDataBigIntegerKey, OrderDataBigInteger>[ReRuns];
A_Iteration_Initialize(ReRuns, sd);
private static void A_Iteration_Initialize(int repeatCount, IList<SortedList<OrderDataBigIntegerKey, OrderDataBigInteger>> collection)
var sw = Stopwatch.StartNew();
Dictionary<OrderDataBigIntegerKey, OrderDataBigInteger> prefillDictionary = _prefillArray.ToDictionary(static pair => GetKey(pair), static p => p);
int count = prefillDictionary.Count;
OrderDataBigIntegerKey[] k = prefillDictionary.Keys.ToArray();
OrderDataBigInteger[] v = prefillDictionary.Values.ToArray();
Parallel.For(0, repeatCount, i =>
var help = new SortedList<OrderDataBigIntegerKey, OrderDataBigInteger>(count);
var tr = __makeref (help);
SizeFieldInfo!.SetValueDirect(tr, count);
Array.Copy(k, (OrderDataBigIntegerKey[])KeysFieldInfo.GetValueDirect(tr)!, count);
Array.Copy(v, (OrderDataBigInteger[])ValuesFieldInfo.GetValueDirect(tr)!, count);
Console.WriteLine($@"{DateTime.Now} - A_Iteration_Initialize Fill SortedList: {sw.Elapsed}");
private static void A_Iteration_Initialize(int repeatCount, IList<SortedDictionary<OrderDataBigIntegerKey, OrderDataBigInteger>> collection)
var sw = Stopwatch.StartNew();
Dictionary<OrderDataBigIntegerKey, OrderDataBigInteger> prefillDictionary = _prefillArray.ToDictionary(static pair => GetKey(pair), static p => p);
var prefillSortedDictionary = new SortedDictionary<OrderDataBigIntegerKey, OrderDataBigInteger>(prefillDictionary);
Parallel.For(0, repeatCount, i =>
collection[i] = new SortedDictionary<OrderDataBigIntegerKey, OrderDataBigInteger>(prefillSortedDictionary);
Console.WriteLine($@"{DateTime.Now} - A_Iteration_Initialize Fill SortedDictionary: {sw.Elapsed}");
private static void A_Iteration_Initialize(int repeatCount, IList<ImmutableSortedDictionary<OrderDataBigIntegerKey, OrderDataBigInteger>> collection)
var sw = Stopwatch.StartNew();
IEnumerable<KeyValuePair<OrderDataBigIntegerKey, OrderDataBigInteger>> prefill = _prefillArray.Select(static o => new KeyValuePair<OrderDataBigIntegerKey, OrderDataBigInteger>(GetKey(o), o));
var builder = ImmutableSortedDictionary.CreateBuilder<OrderDataBigIntegerKey, OrderDataBigInteger>();
builder.AddRange(prefill);
ImmutableSortedDictionary<OrderDataBigIntegerKey, OrderDataBigInteger> cacheDictionary = builder.ToImmutable();
Parallel.For(0, repeatCount, i =>
collection[i] = cacheDictionary;
Console.WriteLine($@"{DateTime.Now} - A_Iteration_Initialize Fill ImmutableSortedDictionary: {sw.Elapsed}");
private static void A_Static_Global_Setup(int prefill, int priceRange)
_prefillArray = GetOrderDataArray(prefill, priceRange);
private static OrderDataBigIntegerKey GetKey(OrderDataBigInteger data)
ArgumentNullException.ThrowIfNull(data.Price);
return new OrderDataBigIntegerKey(data.Price, data.OrderId);
private static OrderDataBigInteger[] GetOrderDataArray(int count, int priceRange)
var ret = new OrderDataBigInteger[count];
Parallel.For(0, count, i =>
ret[i] = GetSingleOrderData(i, priceRange);
private static OrderDataBigInteger GetSingleOrderData(int i, int priceRange)
long val = rnd.NextInt64(0, priceRange);
var price = new BigInteger(val);
var orderId = new Guid(i, 0, 0, [0, 0, 0, 0, 0, 0, 0, 0]);
return new OrderDataBigInteger(price, orderId, 1);
public interface IOrderData<T>
Guid OrderId { get; init; }
T Quantity { get; init; }
T UsedQuantity { get; init; }
public interface IOrderDataKey<T> : IComparable<IOrderDataKey<T>>
Guid OrderId { get; init; }
public readonly record struct OrderDataBigInteger(BigInteger Price, Guid OrderId, BigInteger Quantity);
public readonly record struct OrderDataBigIntegerKey(BigInteger Price, Guid OrderId) : IComparable<OrderDataBigIntegerKey>, IComparisonOperators<OrderDataBigIntegerKey, OrderDataBigIntegerKey, bool>
public int CompareTo(OrderDataBigIntegerKey other)
int result = Price.CompareTo(other.Price);
return result != 0 ? result : OrderId.CompareTo(other.OrderId);
public static bool operator>(OrderDataBigIntegerKey left, OrderDataBigIntegerKey right)
return left.CompareTo(right) > 0;
public static bool operator >=(OrderDataBigIntegerKey left, OrderDataBigIntegerKey right)
return left.CompareTo(right) >= 0;
public static bool operator <(OrderDataBigIntegerKey left, OrderDataBigIntegerKey right)
return left.CompareTo(right) < 0;
public static bool operator <=(OrderDataBigIntegerKey left, OrderDataBigIntegerKey right)
return left.CompareTo(right) <= 0;
public int CompareTo(object? other)
if (other is not OrderDataBigIntegerKey key)