C#で確保済みbyte配列でmallocモドキ
GC任せにしてbyte配列何度も確保したくないし、Spanが来るから積極的に部分配列を使いたい。 byteに対して標準Cライブラリのmallocみたいなことできないかなーとほんのり思っていました。
mallocぽいというのはこういう感じですね。フラグメンテーション上等!
やってみたらSortedSetが優秀だったのでえらくあっさり作れました…
スレッドセーフではないですけどね。シリアライズ用にちょいちょいSpan
using System; using System.Collections.Generic; public struct ByteSegment : IComparable<ByteSegment> { public int Offset { get; } public int Length { get; } public ByteSegment(int offset, int length) { Offset = offset; Length = length; } public int CompareTo(ByteSegment other) { return Offset - other.Offset; } public override string ToString() { return $"{Offset},{Length}"; } } public class BytePool { SortedSet<ByteSegment> _segments = new SortedSet<ByteSegment>(); public byte[] Buffer { get; private set; } public BytePool(int capacity) { Buffer = new byte[capacity]; } public ByteSegment Alloc(int length) { int offset = 0; if(_segments.Count != 0) { foreach(var s in _segments) { var desired = offset + length; if(s.Offset < desired) { offset = s.Offset + s.Length; continue; } else { break; } } } if (Buffer.Length < (offset + length)) throw new Exception("無理ぽ"); var newSegment = new ByteSegment(offset, length); _segments.Add(newSegment); return newSegment; } public void Release(ByteSegment segment) { _segments.Remove(segment); } public Span<byte> ToSpan(ByteSegment segment) { return new Span<byte>(Buffer, segment.Offset, segment.Length); } }