public unsafe void DirectPointer(RetainableMemory <int> rm) { var rounds = 1_000; long sum = 0; using (Benchmark.Run("DirectPointer", rm.Length * rounds)) { var head = rm.Length / 2; var len = rm.Length; var ptr = (int *)rm.Pointer; for (int r = 0; r < rounds; r++) { for (int i = 0; i < len; i++) { sum += ptr[i]; } } } if (sum < 1000) { throw new InvalidOperationException(); } }
public void MemoryAccessVecViaDbVecStorageUnsafe(RetainableMemory <int> rm) { var rounds = TestUtils.GetBenchCount(100_000, 100); long sum = 0; using (Benchmark.Run("DbVecStorageUnsafe (+)", rm.Length * rounds)) { DataBlockLike db = new DataBlockLike { Rm = rm, Vec = rm.GetVec().AsVec(), RetainedVec = RetainedVec.Create(rm, 0, rm.Length, true) }; for (int r = 0; r < rounds; r++) { for (long i = 0; i < rm.Length; i++) { sum += db.RetainedVec.Vec.UnsafeGetUnaligned <int>((IntPtr)i); } } } if (sum < 1000) { throw new InvalidOperationException(); } }
public unsafe void RingVecUtilIndexToOffset(RetainableMemory <int> rm) { var rounds = 1_000; long sum = 0; using (Benchmark.Run("RingVecUtil", rm.Length * rounds)) { var head = rm.Length / 2; var len = rm.Length; var ptr = (int *)rm.Pointer; for (int r = 0; r < rounds; r++) { for (int i = 0; i < len; i++) { sum += ptr[RingVecUtil.IndexToOffset(i, head, len)]; } } } if (sum < 1000) { throw new InvalidOperationException(); } }
public static VectorStorage Create <T>(RetainableMemory <T> memorySource, int memoryStart, int memoryLength, int stride = 1, int elementLength = -1, bool externallyOwned = false) { Debug.Assert(stride > 0); var vs = ObjectPool.Allocate(); vs._memorySource = memorySource; if (!externallyOwned) { vs._memoryHandle = vs._memorySource.Pin(0); } vs._vec = memorySource.Vec.AsVec().Slice(memoryStart, memoryLength); vs._stride = stride; var numberOfStridesFromZero = vs._vec.Length / stride; if (stride > 1) { // last full stride could be incomplete but with the current logic we will access only the first element if (vs._vec.Length - numberOfStridesFromZero * stride > 0) { numberOfStridesFromZero++; } } if (elementLength != -1) { if ((uint)elementLength <= numberOfStridesFromZero) { numberOfStridesFromZero = elementLength; } else { ThrowHelper.ThrowArgumentOutOfRangeException("elementLength"); } } vs._length = numberOfStridesFromZero; return(vs); }
public void MemoryAccessVecViaFieldDangerous(RetainableMemory <int> rm) { long sum = 0; using (Benchmark.Run("FieldUnsafe", rm.Length)) { for (long i = 0; i < rm.Length; i++) { sum += rm.Vec.UnsafeGetUnaligned <int>((IntPtr)i); } } if (sum < 1000) { throw new InvalidOperationException(); } }
public void MemoryAccessVecViaLocalDangerous(RetainableMemory <int> rm) { long sum = 0; using (Benchmark.Run("LocalDangerous", rm.Length)) { var vec = rm.Vec; for (int i = 0; i < rm.Length; i++) { sum += vec.DangerousGetUnaligned <int>(i); } } if (sum < 1000) { throw new InvalidOperationException(); } }
public void MemoryFieldBench_Field(RetainableMemory <int> rm) { var rounds = TestUtils.GetBenchCount(100_000_000, 1000); long sum = 0; using (Benchmark.Run("Field", rounds)) { for (int r = 0; r < rounds; r++) { sum += rm.Memory.Length; } } if (sum < 1000) { throw new InvalidOperationException(); } }
public unsafe void MemoryAccessViaPointer(RetainableMemory <int> rm) { long sum = 0; using (Benchmark.Run("Pointer", rm.Length)) { var ptr = (int *)rm.Pointer; for (int i = 0; i < rm.Length; i++) { sum += ptr[i]; } } if (sum < 1000) { throw new InvalidOperationException(); } }
public void MemoryAccessVecViaHelperUnsafe(RetainableMemory <int> rm) { long sum = 0; using (Benchmark.Run("HelperUnsafe", rm.Length)) { object obj = rm; for (long i = 0; i < rm.Length; i++) { sum += RetainableMemoryHelper.GetVecRef(obj).UnsafeGetUnaligned <int>((IntPtr)i); } } if (sum < 1000) { throw new InvalidOperationException(); } }
public unsafe void MemoryAccessViaPointer(RetainableMemory <int> rm) { var rounds = TestUtils.GetBenchCount(100_000, 100); long sum = 0; using (Benchmark.Run("Pointer", rm.Length * rounds)) { var ptr = (int *)rm.Pointer; for (int r = 0; r < rounds; r++) { for (long i = 0; i < rm.Length; i++) { sum += ptr[i]; } } } // if (sum < 1000) // throw new InvalidOperationException(); }
public void MemoryAccessVecViaDbVecStorageDangerous(RetainableMemory <int> rm) { long sum = 0; using (Benchmark.Run("DbVecStorageDangerous (_)", rm.Length)) { DataBlockLike db = new DataBlockLike { Rm = rm, Vec = rm.Vec, VecStorage = VecStorage.Create(rm, 0, rm.Length, true) }; for (int i = 0; i < rm.Length; i++) { sum += db.VecStorage.Vec.DangerousGetUnaligned <int>(i); } } if (sum < 1000) { throw new InvalidOperationException(); } }
public unsafe void MemoryAccessVecViaDbVecPointer(RetainableMemory <int> rm) { long sum = 0; using (Benchmark.Run("DbVecPointer (*)", rm.Length)) { DataBlockLike db = new DataBlockLike { Rm = rm, Vec = rm.Vec, Ptr = (int *)rm.Pointer }; for (int i = 0; i < rm.Length; i++) { sum += Unsafe.ReadUnaligned <int>(ref Unsafe.As <int, byte>(ref Unsafe.Add <int>(ref Unsafe.AsRef <int>((void *)db.Vec._byteOffset), i))); } } if (sum < 1000) { throw new InvalidOperationException(); } }
public void MemoryAccessVecViaDbVecUnsafe(RetainableMemory <int> rm) { long sum = 0; using (Benchmark.Run("DbVecUnsafe (+)", rm.Length)) { DataBlockLike db = new DataBlockLike { Rm = rm, Vec = rm.Vec }; for (long i = 0; i < rm.Length; i++) { sum += db.Vec.UnsafeGetUnaligned <int>((IntPtr)i); } } if (sum < 1000) { throw new InvalidOperationException(); } }
public void MemoryAccessVecViaDbHelperUnsafeGetRef(RetainableMemory <int> rm) { long sum = 0; DataBlockLike db = new DataBlockLike { Rm = rm, Vec = rm.Vec }; using (Benchmark.Run("DbHelperUnsafeGet (^)", rm.Length)) { for (long i = 0; i < rm.Length; i++) { sum += Unsafe.As <PrivateMemory <byte> >(db.Rm).Vec.UnsafeGetUnaligned <int>((IntPtr)i); } } if (sum < 1000) { throw new InvalidOperationException(); } }
public void MemoryAccessVecViaDbHelperDangerous(RetainableMemory <int> rm) { long sum = 0; using (Benchmark.Run("DbHelperDangerous (^)", rm.Length)) { DataBlockLike db = new DataBlockLike { Rm = rm }; for (int i = 0; i < rm.Length; i++) { sum += RetainableMemoryHelper.GetVecRef(db.Rm).DangerousGetUnaligned <int>(i); } } if (sum < 1000) { throw new InvalidOperationException(); } }
public void MemoryAccessVecViaMemSpan(RetainableMemory <int> rm) { var rounds = TestUtils.GetBenchCount(10_000, 100); long sum = 0; using (Benchmark.Run("MemSpan", rm.Length * rounds)) { for (int r = 0; r < rounds; r++) { for (long i = 0; i < rm.Length; i++) { sum += rm.Memory.Span[(int)i]; } } } if (sum < 1000) { throw new InvalidOperationException(); } }
public void Sum(RetainableMemory <int> rm) { var rounds = TestUtils.GetBenchCount(100_000, 100); long sum = 0; using (Benchmark.Run("Sum (CPU Hz)", rm.Length * rounds)) { for (int r = 0; r < rounds; r++) { for (long i = 0; i < rm.Length; i++) { sum += i; } } } if (sum < 1000) { throw new InvalidOperationException(); } }
public void MemoryAccessVecViaLocalUnsafe(RetainableMemory <int> rm) { var rounds = TestUtils.GetBenchCount(10_000, 100); long sum = 0; using (Benchmark.Run("LocalUnsafe", rm.Length * rounds)) { var vec = rm.GetVec().AsVec(); for (int r = 0; r < rounds; r++) { for (long i = 0; i < rm.Length; i++) { sum += vec.UnsafeGetUnaligned <int>((IntPtr)i); } } } if (sum < 1000) { throw new InvalidOperationException(); } }
public unsafe void MemoryAccessViaArray(RetainableMemory <int> rm, int[] arr) { var rounds = TestUtils.GetBenchCount(100_000, 100); DataBlockLike db = new DataBlockLike { Rm = rm, arr = arr }; long sum = 0; using (Benchmark.Run("Array", rm.Length * rounds)) { for (int r = 0; r < rounds; r++) { for (int i = 0; i < db.arr.Length; i++) { sum += db.arr[i]; } } } if (sum < 1000) { throw new InvalidOperationException(); } }
public unsafe void MemoryAccessVecViaDbVecPointer(RetainableMemory <int> rm) { var rounds = TestUtils.GetBenchCount(100_000, 100); long sum = 0; using (Benchmark.Run("DbVecPointer (*)", rm.Length * rounds)) { DataBlockLike db = new DataBlockLike { Rm = rm, Vec = rm.GetVec().AsVec(), Ptr = (int *)rm.Pointer }; for (int r = 0; r < rounds; r++) { for (long i = 0; i < rm.Length; i++) { sum += Unsafe.ReadUnaligned <int>(ref Unsafe.As <int, byte>(ref Unsafe.Add <int>(ref Unsafe.AsRef <int>((void *)db.Vec._byteOffset), (IntPtr)i))); } } } if (sum < 1000) { throw new InvalidOperationException(); } }
public void MemoryAccessVecViaDbVecDangerous(RetainableMemory <int> rm) { long sum = 0; var rounds = TestUtils.GetBenchCount(10_000, 100); using (Benchmark.Run("DbVecDangerous (+)", rm.Length * rounds)) { DataBlockLike db = new DataBlockLike { Rm = rm, Vec = rm.GetVec().AsVec() }; for (int r = 0; r < rounds; r++) { for (int i = 0; i < rm.Length; i++) { sum += db.Vec.DangerousGetUnaligned <int>(i); } } } if (sum < 1000) { throw new InvalidOperationException(); } }
internal int SeriesIncreaseCapacity <TKey, TValue>(int newCapacity = -1) { EnsureSeriesLayout(); EnsureNotSentinel(); // TODO handle OutOfMemory in RentMemory, operation must be atomic in a sense that any error does not change existing data, no partial updates. // TODO _rowIndex.Vec.Length could be already 2x larger because array pool could have returned larger array on previous doubling // TODO (!, new) VS now hides total capacity of RM, we could get RM by casting and here we have types. // But is it always true that unused part of RM is always free and we could just expand to it without copying? // We ignore this now //if (_rowIndex.Vec.Length != _rowIndex.Length) //{ // Console.WriteLine($"_rowIndex.Vec.Length {_rowIndex.Vec.Length} != _rowIndex.Length {_rowIndex.Length}"); //} var ri = _rowKeys; var vals = _values; var minCapacity = Math.Max(newCapacity, Settings.MIN_POOLED_BUFFER_LEN); var newLen = Math.Max(minCapacity, BitUtil.FindNextPositivePowerOfTwo(ri.Vec.Length + 1)); RetainableMemory <TKey>?newRiBuffer = null; VecStorage newRi = default; RetainableMemory <TValue>?newValsBuffer = null; VecStorage newVals = default; try { newRiBuffer = BufferPool <TKey> .MemoryPool.RentMemory(newLen); newRi = VecStorage.Create(newRiBuffer, 0, newRiBuffer.Length); // new buffer could be larger if (ri.Vec.Length > 0) { ri.Vec.AsSpan <TKey>().CopyTo(newRi.Vec.AsSpan <TKey>()); } newValsBuffer = BufferPool <TValue> .MemoryPool.RentMemory(newLen); newVals = VecStorage.Create(newValsBuffer, 0, newValsBuffer.Length); if (vals.Vec.Length > 0) { vals.Vec.AsSpan <TValue>().CopyTo(newVals.Vec.AsSpan <TValue>()); } } catch (OutOfMemoryException) { if (newRi != default) { newRi.Dispose(); } else { newRiBuffer?.DecrementIfOne(); } if (newVals != default) { newVals.Dispose(); } else { newValsBuffer?.DecrementIfOne(); } // TODO log this event return(-1); } try { try { } finally { // we have all needed buffers, must switch in one operation _rowKeys = newRi; _values = newVals; ri.Dispose(); vals.Dispose(); } return(_rowKeys.Vec.Length); } catch { return(-1); } }