/// <param name="outHighway">The memory highway, used for sending tiles. /// If null, a HeapHighway with default capacity of 65KB is used.</param> public XCfg(BeamerCfg bcfg, XLogCfg log, IMemoryHighway outHighway) { this.bcfg = bcfg; this.log = log; this.outHighway = outHighway != null ? outHighway : new HeapHighway(new HighwaySettings(Beamer.UDP_MAX), Beamer.UDP_MAX); }
public static MemoryFragment Serialize <T>(this T o, IMemoryHighway hw, Action <MemoryStream> pre = null) { if (hw == null || hw.IsDisposed) { throw new ArgumentNullException("hw"); } using (var ms = new MemoryStream()) { if (pre != null) { pre(ms); } var bf = new BinaryFormatter(); bf.Serialize(ms, o); var f = hw.AllocFragment((int)ms.Length); var fs = f.CreateStream(); ms.Seek(0, SeekOrigin.Begin); fs.Seek(0, SeekOrigin.Begin); ms.CopyTo(fs); return(f); } }
/// <summary> /// Creates a new Highway stream instance. /// </summary> /// <param name="hw">The highway to use for storage.</param> /// <param name="fragmentSize">The size of the fragments.</param> public HighwayStream(IMemoryHighway hw, int fragmentSize) { Highway = hw ?? throw new ArgumentNullException(); if (fragmentSize < 1) { throw new ArgumentOutOfRangeException("fragmentSize"); } FragmentSize = fragmentSize; }
internal Exchange( XPU xpu, int refID, int xflags, int errorCode, string resID, Span <byte> data, IMemoryHighway hw) { XPU = xpu; var resBytes = Encoding.UTF8.GetBytes(resID); ResIDLen = (ushort)resBytes.Length; var fl = data.Length + ResIDLen + HEADER_LEN; Fragment = hw.AllocFragment(fl); if (Fragment == null) { throw new ArgumentNullException("Fragment"); } var pos = 0; this.ID = xpu.nextExchangeID(); this.RefID = refID; this.Flags = xflags; this.Created = DateTime.Now.Ticks; this.ErrorCode = errorCode; this.state = (int)XState.Created; this.ResID = resID; pos = Fragment.Write(EXCHANGE_TYPE_ID, pos); pos = Fragment.Write(ID, pos); pos = Fragment.Write(refID, pos); pos = Fragment.Write((int)xflags, pos); pos = Fragment.Write(Created, pos); pos = Fragment.Write(errorCode, pos); pos = Fragment.Write(ResIDLen, pos); if (resBytes.Length > 0) { pos = Fragment.Write(resBytes, pos); } DataOffset = pos; if (data.Length > 0) { Fragment.Write(data, pos); } }
public Block(int id, int totalSize, ushort tileSize, IMemoryHighway hw) { ID = id; TileSize = tileSize; TotalSize = totalSize; TilesCount = totalSize / tileSize; if (TotalSize > tileSize && TotalSize % tileSize != 0) { TilesCount++; } if (TilesCount == 0) { TilesCount = 1; } IsIncoming = true; fragment = hw.AllocFragment(totalSize); tileMap = new BitMask(TilesCount); }
/// <summary> /// Creates a RayBeamer configuration instance. /// </summary> /// <param name="receiveHighway">For the blocks, i.e. do not assume lengths.</param> /// <param name="tileXHighway">For tile exchanges. Pass null to init with a heap hw with 65K lanes.</param> /// <param name="logcfg">The logging settings.</param> public BeamerCfg( IMemoryHighway receiveHighway = null, IMemoryHighway tileXHighway = null, IMemoryHighway outHighway = null, BeamerLogCfg logcfg = null) { ReceiveHighway = receiveHighway != null ? receiveHighway : new HeapHighway(); TileExchangeHighway = tileXHighway != null ? tileXHighway : new HeapHighway( new HighwaySettings(ushort.MaxValue, 10000), ushort.MaxValue, ushort.MaxValue, ushort.MaxValue); OutHighway = outHighway != null ? outHighway : new HeapHighway( new HighwaySettings(ushort.MaxValue, 10000), ushort.MaxValue, ushort.MaxValue, ushort.MaxValue); Log = logcfg; }
public static void AllocAndWait(this IMemoryHighway hw, AllocTestArgs args) { var rdm = new Random(); var hwType = hw.GetType().Name; var inParallel = args.InParallel > 0 ? args.InParallel : Environment.ProcessorCount; var T = new Task[inParallel]; var part = args.Count / inParallel; var rem = args.Count % inParallel; var dispCounter = new CountdownEvent(args.Count); for (int i = 0; i < inParallel; i++) { T[i] = Task.Run(async() => { // [!] Do not try catch // Someone must process the remainder var subCount = rem > 0 ? part + Interlocked.Exchange(ref rem, 0) : part; for (int j = 0; j < subCount; j++) { var size = args.RandomizeLength ? rdm.Next(1, args.Size) : args.Size; var allocDelayMS = args.RandomizeAllocDelay && args.AllocDelayMS > 0 ? rdm.Next(0, args.AllocDelayMS) : args.AllocDelayMS; var dispDelayMS = args.RandomizeFragDisposal ? rdm.Next(0, args.FragmentDisposeAfterMS) : args.FragmentDisposeAfterMS; if (allocDelayMS > 0) { await Task.Delay(allocDelayMS); } var frag = hw.AllocFragment(size, args.AllocTries); if (frag == null) { "failed to allocate a fragment. The Highway is full.".AsInfo(ConsoleColor.DarkMagenta); dispCounter.Signal(); continue; } if (args.Trace > 0) { Print.Trace("alloc {0,8} bytes on {1} thread: {2} ", ConsoleColor.Magenta, size, hwType, Thread.CurrentThread.ManagedThreadId); } var t = Task.Run(async() => { if (dispDelayMS > 0) { await Task.Delay(dispDelayMS); } if (args.Trace > 0) { Print.Trace("free {0,8} bytes on {1} thread: {2} ", ConsoleColor.Green, frag.Length, hwType, Thread.CurrentThread.ManagedThreadId); } frag.Dispose(); dispCounter.Signal(); }); } }); } Task.WaitAll(T); if (args.AwaitFragmentDisposal) { dispCounter.Wait(); } }
public XCfg(BeamerCfg bcfg, IMemoryHighway outHighway) : this(bcfg, null, outHighway) { }
async Task Process(AllocType at, Socket client, Action <int> onmessage, bool stop = false) { Print.AsInfo(at.ToString() + Environment.NewLine); try { Print.AsInfo("New client" + Environment.NewLine); IMemoryHighway hw = null; var lanes = new int[] { 1025, 2048 }; switch (at) { case AllocType.Heap: hw = new HeapHighway(lanes); break; case AllocType.MMF: hw = new MappedHighway(lanes); break; case AllocType.Marshal: hw = new MarshalHighway(lanes); break; default: throw new ArgumentNullException(); } using (hw) using (var ns = new NetworkStream(client)) { var header = new byte[4]; var spoon = new byte[16000]; var total = 0; var read = 0; var frameLen = 0; while (!stop) { total = 0; read = await ns.ReadAsync(header, 0, 4).ConfigureAwait(false); Print.AsInfo("Received header bytes: {0}.{1}.{2}.{3}", header[0], header[1], header[2], header[3]); // The other side is gone. // As long as the sender is not disposed/closed the ReadAsync will wait if (read < 1) { Print.AsError("The client is gone."); break; } frameLen = BitConverter.ToInt32(header, 0); if (frameLen < 1) { Print.AsError("Bad header, thread {0}", Thread.CurrentThread.ManagedThreadId); break; } using (var frag = hw.AllocFragment(frameLen)) { Print.AsInfo("Frame length:{0}", frameLen); // The sip length guards against jumping into the next frame var sip = 0; while (total < frameLen && !stop) { sip = frameLen - total; if (sip > spoon.Length) { sip = spoon.Length; } // the read amount could be smaller than the sip read = await ns.ReadAsync(spoon, 0, sip).ConfigureAwait(false); frag.Write(spoon, total, read); total += read; Print.AsInnerInfo("read {0} on thread {1}", read, Thread.CurrentThread.ManagedThreadId); if (total >= frameLen) { onmessage?.Invoke(total); break; } } } } } } catch (MemoryLaneException mex) { Print.AsError(mex.Message); Print.AsError(mex.ErrorCode.ToString()); Print.AsError(mex.StackTrace); } catch (Exception ex) { Print.AsError(ex.Message); } }