public static unsafe T ReadAsPtr <T>(this MemoryStream stream) { var size = TypeHelper <T> .Size; if (size <= 0) { throw new InvalidOperationException("This method should only be used for writing fixed-size types to a stream"); } if (stream is RecyclableMemoryStream) { throw new NotImplementedException("TODO"); } using (var wrapper = RecyclableMemoryManager.GetBuffer(size)) { var threadStaticBuffer = wrapper.Buffer; var value = default(T); var read = 0; while ((read += stream.Read(threadStaticBuffer, read, size - read)) < size) { } fixed(byte *ptr = &threadStaticBuffer[0]) { TypeHelper <T> .Read((IntPtr)ptr, ref value); } return(value); } }
public static unsafe int WriteAsPtr <T>(this MemoryStream stream, T value) { var size = TypeHelper <T> .Size; if (size <= 0) { throw new InvalidOperationException("This method should only be used for writing fixed-size types to a stream"); } // NB do not use a buffer pool here but instead use a thread-static buffer // that will grow to maximum size of a type. Fixed-size types are usually small. // Take/return is more expensive than the work we do with the pool here. using (var wrapper = RecyclableMemoryManager.GetBuffer(size)) { var threadStaticBuffer = wrapper.Buffer; fixed(byte *ptr = &threadStaticBuffer[0]) { var buffer = new DirectBuffer(threadStaticBuffer.Length, (IntPtr)ptr); TypeHelper <T> .Write(value, ref buffer); } stream.Write(threadStaticBuffer, 0, size); } // NB this is not needed as long as converter.Write guarantees overwriting all Size bytes. // //Array.Clear(_buffer, 0, size); return(size); }
public NetOrchestrator(RecyclableMemoryManager memoryManager, NetPacketCodec codec) { MemoryManager = memoryManager ?? throw new ArgumentNullException(nameof(memoryManager)); Codec = codec ?? throw new ArgumentNullException(nameof(codec)); _packetHolderPool = new PacketHolderPool(StorePacketPredicate); _workers = new List <NetOrchestratorWorker>(); }
public NetManager(RecyclableMemoryManager memoryManager) { MemoryManager = memoryManager ?? throw new ArgumentNullException(nameof(memoryManager)); Codec = new NetPacketCodec(MemoryManager); Orchestrator = new NetOrchestrator(MemoryManager, Codec); Listener = new NetListener(Orchestrator, AcceptConnection); _connections = new HashSet <NetConnection>(); Connections = _connections.AsReadOnly(); }
private static void TestStreamTrimStart() { var mem = new RecyclableMemoryManager(2, 2, 2); var stream = mem.GetStream(6); for (int i = 0; i < 6; i++) { stream.WriteByte((byte)(i % 255)); } stream.TrimStart(3); if (stream.GetBlock(0).Span[0] != 3 || stream.GetBlock(0).Span[1] != 4 || stream.GetBlock(1).Span[0] != 5) { throw new Exception(); } }
public NetPacketCodec(RecyclableMemoryManager memoryManager) { MemoryManager = memoryManager ?? throw new ArgumentNullException(nameof(memoryManager)); Decoder = new NetPacketDecoder(); Encoder = new NetPacketEncoder(); }
public void ThreadStaticBufferVsSharedPool() { for (int r = 0; r < 10; r++) { const int count = 1000000; var sw = new Stopwatch(); sw.Restart(); var sum = 0L; for (var i = 0; i < count; i++) { using (var wrapper = RecyclableMemoryManager.GetBuffer(RecyclableMemoryManager.StaticBufferSize)) { wrapper.Buffer[0] = 123; sum += wrapper.Buffer[0] + wrapper.Buffer[1]; } } Assert.IsTrue(sum > 0); sw.Stop(); Console.WriteLine($"Threadlocal {sw.ElapsedMilliseconds}"); sw.Restart(); sum = 0L; for (var i = 0; i < count; i++) { using (var wrapper = RecyclableMemoryManager.GetBuffer(RecyclableMemoryManager.StaticBufferSize + 1)) { wrapper.Buffer[0] = 123; sum += wrapper.Buffer[0] + wrapper.Buffer[1]; } } Assert.IsTrue(sum > 0); sw.Stop(); Console.WriteLine($"GetBuffer via pool {sw.ElapsedMilliseconds}"); sw.Restart(); sum = 0L; for (var i = 0; i < count; i++) { var buffer = ArrayPool <byte> .Shared.Rent(RecyclableMemoryManager.StaticBufferSize); buffer[0] = 123; sum += buffer[0] + buffer[1]; ArrayPool <byte> .Shared.Return(buffer, true); } Assert.IsTrue(sum > 0); sw.Stop(); Console.WriteLine($"Direct ArrayPool with StaticBufferSize {sw.ElapsedMilliseconds}"); sw.Restart(); sum = 0L; for (var i = 0; i < count; i++) { var buffer = ArrayPool <byte> .Shared.Rent(RecyclableMemoryManager.StaticBufferSize + 1); buffer[0] = 123; sum += buffer[0] + buffer[1]; ArrayPool <byte> .Shared.Return(buffer, true); } Assert.IsTrue(sum > 0); sw.Stop(); Console.WriteLine($"Direct ArrayPool with StaticBufferSize + 1 {sw.ElapsedMilliseconds}"); sw.Restart(); sum = 0L; for (var i = 0; i < count; i++) { var buffer = new byte[RecyclableMemoryManager.StaticBufferSize]; buffer[0] = 123; sum += buffer[0] + buffer[1]; } Assert.IsTrue(sum > 0); sw.Stop(); Console.WriteLine($"GC StaticBufferSize {sw.ElapsedMilliseconds}"); sw.Restart(); sum = 0L; for (var i = 0; i < count; i++) { var buffer = new byte[RecyclableMemoryManager.StaticBufferSize + 1]; buffer[0] = 123; sum += buffer[0] + buffer[1]; } Assert.IsTrue(sum > 0); sw.Stop(); Console.WriteLine($"GC StaticBufferSize + 1 {sw.ElapsedMilliseconds}"); Console.WriteLine("---------------------"); } }