рдореЗрдореЛрд░реА рдФрд░ рд╕реНрдкреИрди рдкреАрдЯреАред 3


рдореЗрдореЛрд░реА <T> рдФрд░ ReadOnlyMemory <T>


Memory<T> рдФрд░ Span<T> рдмреАрдЪ рджреЛ рджреГрд╢реНрдп рдЕрдВрддрд░ рд╣реИрдВред рдкрд╣рд▓рд╛ рдпрд╣ рд╣реИ рдХрд┐ Memory<T> рдкреНрд░рдХрд╛рд░ рдореЗрдВ ref рдкреНрд░рдХрд╛рд░ рд╢рд╛рдорд┐рд▓ рдирд╣реАрдВ рд╣реИред рджреВрд╕рд░реЗ рд╢рдмреНрджреЛрдВ рдореЗрдВ, Memory<T> рдкреНрд░рдХрд╛рд░ рдХреЛ рд╕реНрдерд╛рдиреАрдп рдЪрд░, рдпрд╛ рд╡рд┐рдзрд┐ рдкреИрд░рд╛рдореАрдЯрд░, рдпрд╛ рдЗрд╕рдХреЗ рд▓реМрдЯрд╛ рдореВрд▓реНрдп рдФрд░ рдвреЗрд░ рдкрд░ рджреЛрдиреЛрдВ рд╕реНрдЯреИрдХ рдкрд░ рдЖрд╡рдВрдЯрд┐рдд рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ, рд╡рд╣рд╛рдВ рд╕реЗ рд╕реНрдореГрддрд┐ рдореЗрдВ рдХреБрдЫ рдбреЗрдЯрд╛ рд╕рдВрджрд░реНрднрд┐рдд рдХрд░рддрд╛ рд╣реИред рд╣рд╛рд▓рд╛рдБрдХрд┐, рдпрд╣ рдЫреЛрдЯрд╛ рдЕрдВрддрд░ Span<T> рдХреА рддреБрд▓рдирд╛ рдореЗрдВ Memory<T> рдХреЗ рд╡реНрдпрд╡рд╣рд╛рд░ рдФрд░ рдХреНрд╖рдорддрд╛рдУрдВ рдореЗрдВ рдмрд╣реБрдд рдмрдбрд╝рд╛ рдЕрдВрддрд░ рдкреИрджрд╛ рдХрд░рддрд╛ рд╣реИред Span<T> рд╡рд┐рдкрд░реАрдд рдХреБрдЫ рдбреЗрдЯрд╛ рдмрдлрд░ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдХреБрдЫ рддрд░реАрдХреЛрдВ рдХреЗ рд▓рд┐рдП рдПрдХ рдЙрдкрдХрд░рдг рд╣реИ , Memory<T> рдкреНрд░рдХрд╛рд░ рдХреЛ рдмрдлрд░ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдЬрд╛рдирдХрд╛рд░реА рд╕рдВрдЧреНрд░рд╣реАрдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдбрд┐рдЬрд╝рд╛рдЗрди рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ, рд▓реЗрдХрд┐рди рдЗрд╕реЗ рд╕рдВрднрд╛рд▓рдиреЗ рдХреЗ рд▓рд┐рдП рдирд╣реАрдВред рдЗрд╕ рдкреНрд░рдХрд╛рд░, рдПрдкреАрдЖрдИ рдореЗрдВ рдЕрдВрддрд░ рд╣реИред


  • Memory<T> рдкрд╛рд╕ рдЙрд╕ рдбреЗрдЯрд╛ рддрдХ рдкрд╣реБрдВрдЪрдиреЗ рдХреЗ рддрд░реАрдХреЗ рдирд╣реАрдВ рд╣реИрдВ рдЬрд┐рд╕рдХреЗ рд▓рд┐рдП рд╡рд╣ рдЬрд┐рдореНрдореЗрджрд╛рд░ рд╣реИред рдЗрд╕рдХреЗ рдмрдЬрд╛рдп, рдЗрд╕рдореЗрдВ Span рдкреНрд░реЙрдкрд░реНрдЯреА рдФрд░ Slice рд╡рд┐рдзрд┐ рд╣реЛрддреА рд╣реИ рдЬреЛ Span рдкреНрд░рдХрд╛рд░ рдХрд╛ рдПрдХ рдЙрджрд╛рд╣рд░рдг Span ред
  • рдЗрд╕рдХреЗ рдЕрддрд┐рд░рд┐рдХреНрдд, Memory<T> рдореЗрдВ Pin() рд╡рд┐рдзрд┐ рдХрд╛ рдЙрдкрдпреЛрдЧ рдкрд░рд┐рджреГрд╢реНрдпреЛрдВ рдХреЗ рд▓рд┐рдП рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ рдЬрдм рдПрдХ рд╕рдВрдЧреНрд░рд╣реАрдд рдмрдлрд░ рдбреЗрдЯрд╛ рдХреЛ unsafe рдХреЛрдб рдореЗрдВ рдкрд╛рд░рд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рдирд╛ рдЪрд╛рд╣рд┐рдПред рдпрджрд┐ .NET рдореЗрдВ рдореЗрдореЛрд░реА рдЖрд╡рдВрдЯрд┐рдд рд╣реЛрдиреЗ рдкрд░ рдЗрд╕ рд╡рд┐рдзрд┐ рдХреЛ рдХреЙрд▓ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рддреЛ рдмрдлрд░ рдкрд┐рди рдХрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛ рдФрд░ GC рд╕рдХреНрд░рд┐рдп рд╣реЛрдиреЗ рдкрд░ рд╕реНрдерд╛рдирд╛рдВрддрд░рд┐рдд рдирд╣реАрдВ рд╣реЛрдЧрд╛ред рдпрд╣ рд╡рд┐рдзрд┐ MemoryHandle рд╕рдВрд░рдЪрдирд╛ рдХрд╛ рдПрдХ рдЙрджрд╛рд╣рд░рдг MemoryHandle , рдЬреЛ рдЬреАрд╡рди рднрд░ рдХреЗ рдПрдХ рдЦрдВрдб рдХреЛ рдЗрдВрдЧрд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдФрд░ рдореЗрдореЛрд░реА рдореЗрдВ рд╕рд░рдгреА рдмрдлрд░ рдХреЛ рдкрд┐рди рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП GCHandle рдХреЛ GCHandle рдХрд░рддреА рд╣реИред

рдпрд╣ рдЕрдзреНрдпрд╛рдп рд░реВрд╕реА рд╕реЗ рд╕рдВрдпреБрдХреНрдд рд░реВрдк рд╕реЗ рд▓реЗрдЦрдХ рджреНрд╡рд╛рд░рд╛ рдФрд░ рдкреЗрд╢реЗрд╡рд░ рдЕрдиреБрд╡рд╛рджрдХреЛрдВ рджреНрд╡рд╛рд░рд╛ рдЕрдиреБрд╡рд╛рджрд┐рдд рдХрд┐рдпрд╛ рдЧрдпрд╛ рдерд╛ ред рдЖрдк рд░реВрд╕реА рдпрд╛ рдЕрдВрдЧреНрд░реЗрдЬреА рд╕реЗ рдХрд┐рд╕реА рдЕрдиреНрдп рднрд╛рд╖рд╛ рдореЗрдВ рдЕрдиреБрд╡рд╛рдж рдХрд░рдиреЗ рдореЗрдВ рд╣рдорд╛рд░реА рдорджрдж рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ, рдореБрдЦреНрдпрддрдГ рдЪреАрдиреА рдпрд╛ рдЬрд░реНрдорди рдореЗрдВред

рдЗрд╕рдХреЗ рдЕрд▓рд╛рд╡рд╛, рдпрджрд┐ рдЖрдк рд╣рдореЗрдВ рдзрдиреНрдпрд╡рд╛рдж рджреЗрдирд╛ рдЪрд╛рд╣рддреЗ рд╣реИрдВ, рддреЛ рдЖрдк рд╕рдмрд╕реЗ рдЕрдЪреНрдЫрд╛ рддрд░реАрдХрд╛ рдпрд╣ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ рдХрд┐ рд╣рдореЗрдВ рдЧрд┐рддреБрдм рдкрд░ рдПрдХ рд╕реНрдЯрд╛рд░ рджреЗрдирд╛ рд╣реИ рдпрд╛ рд░рд┐рдкреЙрдЬрд┐рдЯрд░реА рдХреЛ рдлреЛрд░реНрдХ рдХрд░рдирд╛ рд╣реИ github / sidristij / dotnetbook ред

рд╣рд╛рд▓рд╛рдВрдХрд┐, рдореЗрд░рд╛ рд╕реБрдЭрд╛рд╡ рд╣реИ рдХрд┐ рд╣рдо рдХрдХреНрд╖рд╛рдУрдВ рдХреЗ рдкреВрд░реЗ рд╕реЗрдЯ рд╕реЗ рдкрд░рд┐рдЪрд┐рдд рд╣реЛрдВред рд╕рдмрд╕реЗ рдкрд╣рд▓реЗ, Memory<T> рд╕рдВрд░рдЪрдирд╛ рдХреЛ рджреЗрдЦреЗрдВ (рдпрд╣рд╛рдВ рдореИрдВ рдХреЗрд╡рд▓ рдЙрди рдкреНрд░рдХрд╛рд░ рдХреЗ рд╕рджрд╕реНрдпреЛрдВ рдХреЛ рджрд┐рдЦрд╛рддрд╛ рд╣реВрдВ рдЬрд┐рдиреНрд╣реЗрдВ рдореИрдВрдиреЗ рд╕рдмрд╕реЗ рдорд╣рддреНрд╡рдкреВрд░реНрдг рдкрд╛рдпрд╛):


  public readonly struct Memory<T> { private readonly object _object; private readonly int _index, _length; public Memory(T[] array) { ... } public Memory(T[] array, int start, int length) { ... } internal Memory(MemoryManager<T> manager, int length) { ... } internal Memory(MemoryManager<T> manager, int start, int length) { ... } public int Length => _length & RemoveFlagsBitMask; public bool IsEmpty => (_length & RemoveFlagsBitMask) == 0; public Memory<T> Slice(int start, int length); public void CopyTo(Memory<T> destination) => Span.CopyTo(destination.Span); public bool TryCopyTo(Memory<T> destination) => Span.TryCopyTo(destination.Span); public Span<T> Span { get; } public unsafe MemoryHandle Pin(); } 

рдЬреИрд╕рд╛ рдХрд┐ рд╣рдо рджреЗрдЦрддреЗ рд╣реИрдВ рдХрд┐ рд╕рдВрд░рдЪрдирд╛ рдореЗрдВ рд╕рд░рдгрд┐рдпреЛрдВ рдХреЗ рдЖрдзрд╛рд░ рдкрд░ рдХрдВрд╕реНрдЯреНрд░рдХреНрдЯрд░ рд╣реИ, рд▓реЗрдХрд┐рди рдСрдмреНрдЬреЗрдХреНрдЯ рдореЗрдВ рдбреЗрдЯрд╛ рд╕рдВрдЧреНрд░рд╣реАрдд рдХрд░рддрд╛ рд╣реИред рдпрд╣ рдЕрддрд┐рд░рд┐рдХреНрдд рд░реВрдк рд╕реЗ рд╕рдВрджрд░реНрдн рд╕реНрдЯреНрд░рд┐рдВрдЧреНрд╕ рдХреЗ рд▓рд┐рдП рд╣реИ, рдЬрд┐рдирдХреЗ рдкрд╛рд╕ рдЙрдирдХреЗ рд▓рд┐рдП рдбрд┐рдЬрд╝рд╛рдЗрди рдХрд┐рдпрд╛ рдЧрдпрд╛ рдПрдХ рдХрдВрд╕реНрдЯреНрд░рдХреНрдЯрд░ рдирд╣реАрдВ рд╣реИ, рд▓реЗрдХрд┐рди AsMemory() string рд╡рд┐рдзрд┐ рдХреЗ рд╕рд╛рде рдЗрд╕рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ, рдпрд╣ ReadOnlyMemory рджреЗрддрд╛ рд╣реИред рд╣рд╛рд▓рд╛рдБрдХрд┐, рдЬреИрд╕рд╛ рдХрд┐ рджреЛрдиреЛрдВ рдкреНрд░рдХрд╛рд░ рдмрд╛рдЗрдирд░реА рд╕рдорд╛рди рд╣реЛрдирд╛ рдЪрд╛рд╣рд┐рдП, Object _object рдлрд╝реАрд▓реНрдб рдХрд╛ рдкреНрд░рдХрд╛рд░ рд╣реИред


рдЗрд╕рдХреЗ рдмрд╛рдж, рд╣рдо MemoryManager рдкрд░ рдЖрдзрд╛рд░рд┐рдд рджреЛ рдХрдВрд╕реНрдЯреНрд░рдХреНрдЯрд░ рджреЗрдЦрддреЗ рд╣реИрдВред рд╣рдо рдЙрдирдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдмрд╛рдж рдореЗрдВ рдмрд╛рдд рдХрд░реЗрдВрдЧреЗред рдПрдХ рдЦрд╛рд▓реА рд╕реЗрдЯ рдХреЗ рд▓рд┐рдП Length (рдЖрдХрд╛рд░) рдФрд░ IsEmpty рдкреНрд░рд╛рдкреНрдд рдХрд░рдиреЗ рдХреЗ рдЧреБрдгред рдЗрд╕рдХреЗ рдЕрд▓рд╛рд╡рд╛, рдПрдХ рд╕рдмрд╕реЗрдЯ рдкрд╛рдиреЗ рдХреЗ рд▓рд┐рдП Slice рд╡рд┐рдзрд┐ рдХреЗ рд╕рд╛рде-рд╕рд╛рде CopyTo рдФрд░ TryCopyTo рдХреА рдкреНрд░рддрд┐рд▓рд┐рдкрд┐ рдмрдирд╛рдиреЗ рдХреЗ рддрд░реАрдХреЗ рднреА рд╣реИрдВред


Memory рдмрд╛рд░реЗ рдореЗрдВ рдмрд╛рдд рдХрд░рддреЗ рд╣реБрдП рдореИрдВ рдЗрд╕ рдкреНрд░рдХрд╛рд░ рдХреЗ рджреЛ рддрд░реАрдХреЛрдВ рдХрд╛ рд╡рд┐рд╕реНрддрд╛рд░ рд╕реЗ рд╡рд░реНрдгрди рдХрд░рдирд╛ рдЪрд╛рд╣рддрд╛ рд╣реВрдВ: Span рд╕рдВрдкрддреНрддрд┐ рдФрд░ Pin рд╡рд┐рдзрд┐ред


рдореЗрдореЛрд░реА <рдЯреА> .Span


 public Span<T> Span { get { if (_index < 0) { return ((MemoryManager<T>)_object).GetSpan().Slice(_index & RemoveFlagsBitMask, _length); } else if (typeof(T) == typeof(char) && _object is string s) { // This is dangerous, returning a writable span for a string that should be immutable. // However, we need to handle the case where a ReadOnlyMemory<char> was created from a string // and then cast to a Memory<T>. Such a cast can only be done with unsafe or marshaling code, // in which case that's the dangerous operation performed by the dev, and we're just following // suit here to make it work as best as possible. return new Span<T>(ref Unsafe.As<char, T>(ref s.GetRawStringData()), s.Length).Slice(_index, _length); } else if (_object != null) { return new Span<T>((T[])_object, _index, _length & RemoveFlagsBitMask); } else { return default; } } } 

рдЕрд░реНрдерд╛рддреН, рд╡реЗ рддрд╛рд░ рдЬреЛ рдкреНрд░рдмрдВрдзрди рдХреЛ рд╕рдВрднрд╛рд▓рддреЗ рд╣реИрдВред рд╡реЗ рдХрд╣рддреЗ рд╣реИрдВ рдХрд┐ рдЕрдЧрд░ рд╣рдо ReadOnlyMemory<T> рдХреЛ Memory<T> рдкрд░рд┐рд╡рд░реНрддрд┐рдд рдХрд░рддреЗ рд╣реИрдВ (рдпреЗ рдЪреАрдЬреЗрдВ рдмрд╛рдЗрдирд░реА рдкреНрд░рддрд┐рдирд┐рдзрд┐рддреНрд╡ рдореЗрдВ рд╕рдорд╛рди рд╣реИрдВ рдФрд░ рдпрд╣рд╛рдВ рддрдХ тАЛтАЛрдХрд┐ рдПрдХ рдЯрд┐рдкреНрдкрдгреА рд╣реИ рдХрд┐ рдЗрди рдкреНрд░рдХрд╛рд░реЛрдВ рдХреЛ рджреНрд╡рд┐рдЖрдзрд╛рд░реА рддрд░реАрдХреЗ рд╕реЗ рдореЗрд▓ рдЦрд╛рдирд╛ рдЪрд╛рд╣рд┐рдП рдХреНрдпреЛрдВрдХрд┐ рдПрдХ рджреВрд╕рд░реЗ рд╕реЗ Unsafe.As рдХреЙрд▓ рдХрд░рдХреЗ Unsafe.As ) рд╕реНрдЯреНрд░рд┐рдВрдЧреНрд╕ рдХреЛ рдмрджрд▓рдиреЗ рдХреЗ рдЕрд╡рд╕рд░ рдХреЗ рд╕рд╛рде рд╣рдореЗрдВ рдПрдХ рдЧреБрдкреНрдд рдХрдХреНрд╖ рдореЗрдВ ~ рдкрд╣реБрдВрдЪ рдорд┐рд▓реЗрдЧреАред рдпрд╣ рдПрдХ рдЕрддреНрдпрдВрдд рдЦрддрд░рдирд╛рдХ рддрдВрддреНрд░ рд╣реИ:


 unsafe void Main() { var str = "Hello!"; ReadOnlyMemory<char> ronly = str.AsMemory(); Memory<char> mem = (Memory<char>)Unsafe.As<ReadOnlyMemory<char>, Memory<char>>(ref ronly); mem.Span[5] = '?'; Console.WriteLine(str); } --- Hello? 

рд╕реНрдЯреНрд░рд┐рдВрдЧ рдЗрдВрдЯрд░реНрдирд┐рдВрдЧ рдХреЗ рд╕рд╛рде рд╕рдВрдпреБрдХреНрдд рдпрд╣ рддрдВрддреНрд░ рдЧрдВрднреАрд░ рдкрд░рд┐рдгрд╛рдо рдкреИрджрд╛ рдХрд░ рд╕рдХрддрд╛ рд╣реИред


рдореЗрдореЛрд░реА <рдЯреА>ред рдкрд┐рди


рджреВрд╕рд░реА рд╡рд┐рдзрд┐ рдЬреЛ рдордЬрдмреВрдд рдзреНрдпрд╛рди рдЖрдХрд░реНрд╖рд┐рдд рдХрд░рддреА рд╣реИ рд╡рд╣ рд╣реИ Pin :


 public unsafe MemoryHandle Pin() { if (_index < 0) { return ((MemoryManager<T>)_object).Pin((_index & RemoveFlagsBitMask)); } else if (typeof(T) == typeof(char) && _object is string s) { // This case can only happen if a ReadOnlyMemory<char> was created around a string // and then that was cast to a Memory<char> using unsafe / marshaling code. This needs // to work, however, so that code that uses a single Memory<char> field to store either // a readable ReadOnlyMemory<char> or a writable Memory<char> can still be pinned and // used for interop purposes. GCHandle handle = GCHandle.Alloc(s, GCHandleType.Pinned); void* pointer = Unsafe.Add<T>(Unsafe.AsPointer(ref s.GetRawStringData()), _index); return new MemoryHandle(pointer, handle); } else if (_object is T[] array) { // Array is already pre-pinned if (_length < 0) { void* pointer = Unsafe.Add<T>(Unsafe.AsPointer(ref array.GetRawSzArrayData()), _index); return new MemoryHandle(pointer); } else { GCHandle handle = GCHandle.Alloc(array, GCHandleType.Pinned); void* pointer = Unsafe.Add<T>(Unsafe.AsPointer(ref array.GetRawSzArrayData()), _index); return new MemoryHandle(pointer, handle); } } return default; } 

рдпрд╣ рдПрдХреАрдХрд░рдг рдХреЗ рд▓рд┐рдП рдПрдХ рдорд╣рддреНрд╡рдкреВрд░реНрдг рд╕рд╛рдзрди рднреА рд╣реИ рдХреНрдпреЛрдВрдХрд┐ рдпрджрд┐ рд╣рдо рдХрд┐рд╕реА рдЕрдирд╡рд╛рдВрдЯреЗрдб рдХреЛрдб рдХреЛ рдПрдХ рдмрдлрд░ рдкрд╛рд╕ рдХрд░рдирд╛ рдЪрд╛рд╣рддреЗ рд╣реИрдВ, рддреЛ рд╣рдореЗрдВ рд╕рд┐рд░реНрдл Pin() рд╡рд┐рдзрд┐ рдХреЛ рдХреЙрд▓ рдХрд░рдиреЗ рдФрд░ рдЗрд╕ рдХреЛрдб рдХреЛ рдПрдХ рдкреЙрдЗрдВрдЯрд░ рдкрд╛рд╕ рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ, рдЗрд╕рд╕реЗ рдХреЛрдИ рдлрд░реНрдХ рдирд╣реАрдВ рдкрдбрд╝рддрд╛ рдХрд┐ Memory<T> рдХрд┐рд╕ рдкреНрд░рдХрд╛рд░ рдХрд╛ рдбреЗрдЯрд╛ рд╕рдВрджрд░реНрднрд┐рдд рдХрд░рддрд╛ рд╣реИред рдпрд╣ рдкреЙрдЗрдВрдЯрд░ рдПрдХ рдкрд░рд┐рдгрд╛рдореА рд╕рдВрд░рдЪрдирд╛ рдХреА рд╕рдВрдкрддреНрддрд┐ рдореЗрдВ рд╕рдВрдЧреНрд░рд╣реАрдд рдХрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛ред


 void PinSample(Memory<byte> memory) { using(var handle = memory.Pin()) { WinApi.SomeApiMethod(handle.Pointer); } } 

рдЗрд╕рд╕реЗ рдХреЛрдИ рдлрд░реНрдХ рдирд╣реАрдВ рдкрдбрд╝рддрд╛ рдХрд┐ рдЗрд╕ рдХреЛрдб рдореЗрдВ Pin() рдХреНрдпрд╛ рдХрд╣рд╛ рдЧрдпрд╛ рдерд╛: рдпрд╣ Memory рд╣реЛ рд╕рдХрддреА рд╣реИ рдЬреЛ рдпрд╛ рддреЛ T[] рдкреНрд░рддрд┐рдирд┐рдзрд┐рддреНрд╡ рдХрд░рддреА рд╣реИ, рдпрд╛ рдПрдХ string рдпрд╛ рдЕрдирд╡рд╛рдВрдЯреЗрдб рдореЗрдореЛрд░реА рдХрд╛ рдмрдлрд░ред GCHandle.Alloc(array, GCHandleType.Pinned) рд╕рд░рдгрд┐рдпреЛрдВ рдФрд░ рд╕реНрдЯреНрд░рд┐рдВрдЧ рдХреЛ рдПрдХ рд╡рд╛рд╕реНрддрд╡рд┐рдХ GCHandle.Alloc(array, GCHandleType.Pinned) рдФрд░ рдЕрдкреНрд░рдмрдВрдзрд┐рдд рдореЗрдореЛрд░реА рдХреЗ рдорд╛рдорд▓реЗ рдореЗрдВ рдХреБрдЫ рднреА рдирд╣реАрдВ рд╣реЛрдЧрд╛ред


MemoryManager, IMemoryOwner, MemoryPool


рд╕рдВрд░рдЪрдирд╛ рдХреНрд╖реЗрддреНрд░реЛрдВ рдХреЛ рдЗрдВрдЧрд┐рдд рдХрд░рдиреЗ рдХреЗ рдЕрд▓рд╛рд╡рд╛, рдореИрдВ рдпрд╣ рдиреЛрдЯ рдХрд░рдирд╛ рдЪрд╛рд╣рддрд╛ рд╣реВрдВ рдХрд┐ рдЕрдиреНрдп рдЗрдХрд╛рдИ рдХреЗ рдЖрдзрд╛рд░ рдкрд░ рджреЛ рдЕрдиреНрдп internal рдкреНрд░рдХрд╛рд░ рдХреЗ рдирд┐рд░реНрдорд╛рддрд╛ рд╣реИрдВ - MemoryManager ред рдпрд╣ рдПрдХ рдХреНрд▓рд╛рд╕рд┐рдХ рдореЗрдореЛрд░реА рдореИрдиреЗрдЬрд░ рдирд╣реАрдВ рд╣реИ рдЬрд┐рд╕реЗ рдЖрдкрдиреЗ рд╕реЛрдЪрд╛ рд╣реЛрдЧрд╛ рдФрд░ рд╣рдо рдЗрд╕рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдмрд╛рдж рдореЗрдВ рдмрд╛рдд рдХрд░рдиреЗ рдЬрд╛ рд░рд╣реЗ рд╣реИрдВред рдХреНрд▓рд╛рд╕рд┐рдХ рдореЗрдореЛрд░реА рдореИрдиреЗрдЬрд░, рдЬрд┐рд╕рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдЖрдкрдиреЗ рд╕реЛрдЪрд╛ рд╣реЛрдЧрд╛ рдФрд░ рд╣рдо рдмрд╛рдж рдореЗрдВ рдЗрд╕рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдмрд╛рдд рдХрд░рдиреЗ рдЬрд╛ рд░рд╣реЗ рд╣реИрдВред Span рддрд░рд╣, Memory рдореЗрдВ рдПрдХ рдиреЗрд╡рд┐рдЧреЗрдЯ рдХреА рдЧрдИ рд╡рд╕реНрддреБ, рдПрдХ рдСрдлрд╕реЗрдЯ рдФрд░ рдПрдХ рдЖрдВрддрд░рд┐рдХ рдмрдлрд░ рдХрд╛ рдЖрдХрд╛рд░ рд╣реЛрддрд╛ рд╣реИред рдзреНрдпрд╛рди рджреЗрдВ рдХрд┐ рдЖрдк рдХреЗрд╡рд▓ рдПрдХ рд╕рд░рдгреА рд╕реЗ Memory рдмрдирд╛рдиреЗ рдХреЗ рд▓рд┐рдП new рдСрдкрд░реЗрдЯрд░ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред рдпрд╛, рдЖрдк рдПрдХ рд╕реНрдЯреНрд░рд┐рдВрдЧ, рдПрдХ рд╕рд░рдгреА рдпрд╛ рд╕рд░рдгреА рд╕реЗ Memory рдмрдирд╛рдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХреНрд╕рдЯреЗрдВрд╢рди рд╡рд┐рдзрд┐рдпреЛрдВ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред рдореЗрд░рд╛ рдорддрд▓рдм рд╣реИ рдХрд┐ рдЗрд╕реЗ рдореИрдиреНрдпреБрдЕрд▓ рд░реВрдк рд╕реЗ рдЕрдкреНрд░рдмрдВрдзрд┐рдд рдореЗрдореЛрд░реА рд╕реЗ рдмрдирд╛рдпрд╛ рдирд╣реАрдВ рдЧрдпрд╛ рд╣реИред рд╣рд╛рд▓рд╛рдБрдХрд┐, рд╣рдо рджреЗрдЦ рд╕рдХрддреЗ рд╣реИрдВ рдХрд┐ MemoryManager рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдЗрд╕ рд╕рдВрд░рдЪрдирд╛ рдХреЛ рдмрдирд╛рдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХ рдЖрдВрддрд░рд┐рдХ рд╡рд┐рдзрд┐ рд╣реИред


рдлрд╝рд╛рдЗрд▓ MemoryManager.cs


 public abstract class MemoryManager<T> : IMemoryOwner<T>, IPinnable { public abstract MemoryHandle Pin(int elementIndex = 0); public abstract void Unpin(); public virtual Memory<T> Memory => new Memory<T>(this, GetSpan().Length); public abstract Span<T> GetSpan(); protected Memory<T> CreateMemory(int length) => new Memory<T>(this, length); protected Memory<T> CreateMemory(int start, int length) => new Memory<T>(this, start, length); void IDisposable.Dispose() protected abstract void Dispose(bool disposing); } 

рдпрд╣ рд╕рдВрд░рдЪрдирд╛ рдПрдХ рдореЗрдореЛрд░реА рд░реЗрдВрдЬ рдХреЗ рдорд╛рд▓рд┐рдХ рдХреЛ рдЗрдВрдЧрд┐рдд рдХрд░рддреА рд╣реИред рджреВрд╕рд░реЗ рд╢рдмреНрджреЛрдВ рдореЗрдВ, Span Memory рд╕рд╛рде рдХрд╛рдо рдХрд░рдиреЗ рд╡рд╛рд▓рд╛ рдПрдХ рдЙрдкрдХрд░рдг рд╣реИ, Memory рдПрдХ рд╡рд┐рд╢реЗрд╖ рдореЗрдореЛрд░реА рд░реЗрдВрдЬ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдЬрд╛рдирдХрд╛рд░реА рд╕рдВрдЧреНрд░рд╣реАрдд рдХрд░рдиреЗ рдХрд╛ рдПрдХ рдЙрдкрдХрд░рдг рд╣реИ рдФрд░ MemoryManager рдЗрд╕ рд░реЗрдВрдЬ рдХреЗ рдЬреАрд╡рдирдХрд╛рд▓ рдХреЛ рдирд┐рдпрдВрддреНрд░рд┐рдд рдХрд░рдиреЗ рдХрд╛ рдПрдХ рдЙрдкрдХрд░рдг рд╣реИ, рдЕрд░реНрдерд╛рдд рдЗрд╕рдХрд╛ рдорд╛рд▓рд┐рдХред рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рд╣рдо NativeMemoryManager<T> рдкреНрд░рдХрд╛рд░ рдХреЛ рджреЗрдЦ рд╕рдХрддреЗ рд╣реИрдВред рдпрджреНрдпрдкрд┐ рдЗрд╕рдХрд╛ рдЙрдкрдпреЛрдЧ рдкрд░реАрдХреНрд╖рдгреЛрдВ рдХреЗ рд▓рд┐рдП рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рдпрд╣ рдкреНрд░рдХрд╛рд░ рд╕реНрдкрд╖реНрдЯ рд░реВрдк рд╕реЗ "рд╕реНрд╡рд╛рдорд┐рддреНрд╡" рдХреА рдЕрд╡рдзрд╛рд░рдгрд╛ рдХрд╛ рдкреНрд░рддрд┐рдирд┐рдзрд┐рддреНрд╡ рдХрд░рддрд╛ рд╣реИред


рдлрд╝рд╛рдЗрд▓ NativeMemoryManager.cs


 internal sealed class NativeMemoryManager : MemoryManager<byte> { private readonly int _length; private IntPtr _ptr; private int _retainedCount; private bool _disposed; public NativeMemoryManager(int length) { _length = length; _ptr = Marshal.AllocHGlobal(length); } public override void Pin() { ... } public override void Unpin() { lock (this) { if (_retainedCount > 0) { _retainedCount--; if (_retainedCount== 0) { if (_disposed) { Marshal.FreeHGlobal(_ptr); _ptr = IntPtr.Zero; } } } } } // Other methods } 

рдЗрд╕рдХрд╛ рдорддрд▓рдм рд╣реИ рдХрд┐ рд╡рд░реНрдЧ Pin() рд╡рд┐рдзрд┐ рдХреЗ рдиреЗрд╕реНрдЯреЗрдб рдХреЙрд▓ рдХреЗ рд▓рд┐рдП рдЕрдиреБрдорддрд┐ рджреЗрддрд╛ рд╣реИ, рдЗрд╕ рдкреНрд░рдХрд╛рд░ unsafe рджреБрдирд┐рдпрд╛ рд╕реЗ рдЙрддреНрдкрдиреНрди рд╕рдВрджрд░реНрднреЛрдВ рдХреА рдЧрд┐рдирддреА рдХрд░рддрд╛ рд╣реИред


Memory рд╕рд╛рде рдирд┐рдХрдЯрддрд╛ рд╕реЗ рдЬреБрдбрд╝реА рдПрдХ рдЕрдиреНрдп рдЗрдХрд╛рдИ MemoryPool рдЬреЛ рдХрд┐ Memory MemoryPool рдЗрдВрд╕реНрдЯреЗрдВрд╕ (рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ IMemoryOwner ) рдХреЛ рдкреВрд▓ IMemoryOwner рд╣реИ:


рдлрд╝рд╛рдЗрд▓ MemoryPool.cs


 public abstract class MemoryPool<T> : IDisposable { public static MemoryPool<T> Shared => s_shared; public abstract IMemoryOwner<T> Rent(int minBufferSize = -1); public void Dispose() { ... } } 

рдЗрд╕рдХрд╛ рдЙрдкрдпреЛрдЧ рдЕрд╕реНрдерд╛рдпреА рдЙрдкрдпреЛрдЧ рдХреЗ рд▓рд┐рдП рдЖрд╡рд╢реНрдпрдХ рдЖрдХрд╛рд░ рдХреЗ рдмрдлрд╝рд░реНрд╕ рдХреЛ рдкрдЯреНрдЯреЗ рдкрд░ рджреЗрдиреЗ рдХреЗ рд▓рд┐рдП рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред рдХрд╛рд░реНрдпрд╛рдиреНрд╡рд┐рдд IMemoryOwner<T> рдЗрдВрдЯрд░рдлрд╝реЗрд╕ рдХреЗ рд╕рд╛рде рдкрдЯреНрдЯреЗ рдХреЗ рдЙрджрд╛рд╣рд░рдгреЛрдВ рдореЗрдВ рдПрд░реЗ рдХреЗ рдкреВрд▓ рдореЗрдВ рдкрдЯреНрдЯреЗ рдкрд░ рджрд┐рдП рдЧрдП рд╕рд░рдгреА рдХреЛ рд╡рд╛рдкрд╕ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП IMemoryOwner<T> Dispose() рд╡рд┐рдзрд┐ рд╣реИред рдбрд┐рдлрд╝реЙрд▓реНрдЯ рд░реВрдк рд╕реЗ, рдЖрдк ArrayMemoryPool рдкрд░ рдирд┐рд░реНрдорд┐рдд рдмрдлрд╝рд░реНрд╕ рдХреЗ рд╕рд╛рдЭрд╛ рдХрд░рдиреЗ рдпреЛрдЧреНрдп рдкреВрд▓ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ:


рдлрд╝рд╛рдЗрд▓ ArrayMemoryPool.cs


 internal sealed partial class ArrayMemoryPool<T> : MemoryPool<T> { private const int MaximumBufferSize = int.MaxValue; public sealed override int MaxBufferSize => MaximumBufferSize; public sealed override IMemoryOwner<T> Rent(int minimumBufferSize = -1) { if (minimumBufferSize == -1) minimumBufferSize = 1 + (4095 / Unsafe.SizeOf<T>()); else if (((uint)minimumBufferSize) > MaximumBufferSize) ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.minimumBufferSize); return new ArrayMemoryPoolBuffer(minimumBufferSize); } protected sealed override void Dispose(bool disposing) { } } 

рдЗрд╕ рд╡рд╛рд╕реНрддреБрдХрд▓рд╛ рдХреЗ рдЖрдзрд╛рд░ рдкрд░, рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рдЪрд┐рддреНрд░ рд╣реИрдВ:


  • рдпрджрд┐ рдЖрдк рдбреЗрдЯрд╛ ( ReadOnlySpan ) рдкрдврд╝рдирд╛ рдЪрд╛рд╣рддреЗ рд╣реИрдВ рдпрд╛ рдбреЗрдЯрд╛ ( Span ) рдкрдврд╝рдирд╛ рдФрд░ рд▓рд┐рдЦрдирд╛ рдЪрд╛рд╣рддреЗ рд╣реИрдВ, рддреЛ Span рдбреЗрдЯрд╛ рдкреНрд░рдХрд╛рд░ рдХреЛ рдПрдХ рд╡рд┐рдзрд┐ рдкреИрд░рд╛рдореАрдЯрд░ рдХреЗ рд░реВрдк рдореЗрдВ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдЬрд╛рдирд╛ рдЪрд╛рд╣рд┐рдПред рд╣рд╛рд▓рд╛рдВрдХрд┐, рднрд╡рд┐рд╖реНрдп рдХреЗ рдЙрдкрдпреЛрдЧ рдХреЗ рд▓рд┐рдП рдЗрд╕реЗ рдХрд┐рд╕реА рд╡рд░реНрдЧ рдХреЗ рдХреНрд╖реЗрддреНрд░ рдореЗрдВ рд╕рдВрдЧреНрд░рд╣реАрдд рдирд╣реАрдВ рдХрд┐рдпрд╛ рдЬрд╛рдирд╛ рдЪрд╛рд╣рд┐рдПред
  • рдпрджрд┐ рдЖрдкрдХреЛ рдПрдХ рд╡рд░реНрдЧ рдХреЗ рдХреНрд╖реЗрддреНрд░ рд╕реЗ рдбреЗрдЯрд╛ рдмрдлрд░ рдореЗрдВ рдПрдХ рд╕рдВрджрд░реНрдн рд╕рдВрдЧреНрд░рд╣реАрдд рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ, рддреЛ рдЖрдкрдХреЛ рдЕрдкрдиреЗ рд▓рдХреНрд╖реНрдпреЛрдВ рдХреЗ рдЖрдзрд╛рд░ рдкрд░ Memory<T> рдпрд╛ ReadOnlyMemory<T> рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред
  • MemoryManager<T> рдбреЗрдЯрд╛ рдмрдлрд░ (рд╡реИрдХрд▓реНрдкрд┐рдХ) рдХрд╛ рдорд╛рд▓рд┐рдХ рд╣реИред рдпрд╣ рдЖрд╡рд╢реНрдпрдХ рд╣реЛ рд╕рдХрддрд╛ рд╣реИ рдпрджрд┐ рдЖрдкрдХреЛ рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП Pin() рдХреЙрд▓ рдХреА рдЧрдгрдирд╛ рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред рдпрд╛, рдпрджрд┐ рдЖрдкрдХреЛ рдпрд╣ рдЬрд╛рдирдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ рдХрд┐ рдореЗрдореЛрд░реА рдХреИрд╕реЗ рдЬрд╛рд░реА рдХрд░реЗрдВред
  • рдпрджрд┐ Memory рдПрдХ рдЕрдирд╡рд╛рдВрдЯреЗрдб рдореЗрдореЛрд░реА рд░реЗрдВрдЬ рдХреЗ рдЖрд╕рдкрд╛рд╕ рдмрдирд╛рдИ рдЧрдИ рд╣реИ, рддреЛ Pin() рдХреБрдЫ рдирд╣реАрдВ рдХрд░ рд╕рдХрддрд╛ рд╣реИред рд╣рд╛рд▓рд╛рдВрдХрд┐, рд╡рд┐рднрд┐рдиреНрди рдкреНрд░рдХрд╛рд░ рдХреЗ рдмрдлрд╝рд░реНрд╕ рдХреЗ рд╕рд╛рде рдХрд╛рдо рдХрд░рдиреЗ рд╡рд╛рд▓реА рдпрд╣ рд╡рд░реНрджреА: рдкреНрд░рдмрдВрдзрд┐рдд рдФрд░ рдЕрдкреНрд░рдмрдВрдзрд┐рдд рдХреЛрдб рджреЛрдиреЛрдВ рдХреЗ рд▓рд┐рдП рдЗрдВрдЯрд░реИрдХреНрд╢рди рдЗрдВрдЯрд░рдлрд╝реЗрд╕ рд╕рдорд╛рди рд╣реЛрдЧрд╛ред
  • рд╣рд░ рдкреНрд░рдХрд╛рд░ рдХреЗ рд╕рд╛рд░реНрд╡рдЬрдирд┐рдХ рдирд┐рд░реНрдорд╛рддрд╛ рд╣реИрдВред рдЗрд╕рдХрд╛ рдорддрд▓рдм рд╣реИ рдХрд┐ рдЖрдк Span рд╕реАрдзреЗ рдЙрдкрдпреЛрдЧ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ рдпрд╛ Memory рд╕реЗ рдЗрд╕рдХрд╛ рдЙрджрд╛рд╣рд░рдг рдкреНрд░рд╛рдкреНрдд рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред Memory рдХреЛ рдЗрд╕ рддрд░рд╣ рд╕реЗ, рдЖрдк рдЗрд╕реЗ рд╡реНрдпрдХреНрддрд┐рдЧрдд рд░реВрдк рд╕реЗ рдмрдирд╛ рд╕рдХрддреЗ рд╣реИрдВ рдпрд╛ рдЖрдк IMemoryOwner рд╕реНрд╡рд╛рдорд┐рддреНрд╡ рд╡рд╛рд▓реА рдореЗрдореЛрд░реА рд░реЗрдВрдЬ рдмрдирд╛ рд╕рдХрддреЗ рд╣реИрдВ рдФрд░ Memory рджреНрд╡рд╛рд░рд╛ рд╕рдВрджрд░реНрднрд┐рдд рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред MemoryManger рдкрд░ рдЖрдзрд╛рд░рд┐рдд рдХрд┐рд╕реА рднреА рдкреНрд░рдХрд╛рд░ рдХреЛ рдПрдХ рд╡рд┐рд╢рд┐рд╖реНрдЯ рдорд╛рдорд▓реЗ рдХреЗ рд░реВрдк рдореЗрдВ рдорд╛рдирд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ рдЬреЛ рдХреБрдЫ рд╕реНрдерд╛рдиреАрдп рдореЗрдореЛрд░реА рд░реЗрдВрдЬ (рдЬреИрд╕реЗ unsafe рджреБрдирд┐рдпрд╛ рд╕реЗ рд╕рдВрджрд░реНрднреЛрдВ рдХреА рдЧрд┐рдирддреА рдХреЗ рд╕рд╛рде) рдХрд╛ рдорд╛рд▓рд┐рдХ рд╣реИред рдЗрд╕рдХреЗ рдЕрд▓рд╛рд╡рд╛, рдпрджрд┐ рдЖрдкрдХреЛ рдРрд╕реЗ рдмрдлрд╝рд░реНрд╕ (рд▓рдЧрднрдЧ рд╕рдорд╛рди рд░реВрдк рд╕реЗ рдмрдлрд╝рд░реНрд╕ рдХреЗ рд▓рдЧрд╛рддрд╛рд░ рдЯреНрд░реИрдлрд╝рд┐рдХ рдХреА рдЙрдореНрдореАрдж рд╣реИ) рдХреЛ рдкреВрд▓ рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ, рддреЛ рдЖрдк MemoryPool рдкреНрд░рдХрд╛рд░ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред
  • рдпрджрд┐ рдЖрдк рд╡рд╣рд╛рдВ рдбреЗрдЯрд╛ рдмрдлрд░ рдкрд╛рд╕ рдХрд░рдХреЗ unsafe рдХреЛрдб рдХреЗ рд╕рд╛рде рдХрд╛рдо рдХрд░рдиреЗ рдХрд╛ рдЗрд░рд╛рджрд╛ рд░рдЦрддреЗ рд╣реИрдВ, рддреЛ рдЖрдкрдХреЛ Memory рдкреНрд░рдХрд╛рд░ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдирд╛ рдЪрд╛рд╣рд┐рдП рдЬрд┐рд╕рдореЗрдВ Pin() рд╡рд┐рдзрд┐ рд╣реИ рдЬреЛ рд╕реНрд╡рдЪрд╛рд▓рд┐рдд рд░реВрдк рд╕реЗ .NET рд╣реАрдк рдкрд░ рдПрдХ рдмрдлрд░ рдкрд┐рди рдХрд░рддрд╛ рд╣реИ рдпрджрд┐ рдпрд╣ рд╡рд╣рд╛рдВ рдмрдирд╛рдпрд╛ рдЧрдпрд╛ рдерд╛ред
  • рдпрджрд┐ рдЖрдкрдХреЗ рдкрд╛рд╕ рдмрдлрд╝рд░реНрд╕ рдХрд╛ рдХреБрдЫ рдЯреНрд░реИрдлрд╝рд┐рдХ рд╣реИ (рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП рдЖрдк рдХрд┐рд╕реА рдкреНрд░реЛрдЧреНрд░рд╛рдо рдпрд╛ рдбреАрдПрд╕рдПрд▓ рдХрд╛ рдкрд╛рда рдкрд╛рд░реНрд╕ рдХрд░рддреЗ рд╣реИрдВ), рддреЛ MemoryPool рдЯрд╛рдЗрдк рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдирд╛ рдмреЗрд╣рддрд░ рд╣реИред рдЖрдк рдкреВрд▓ рд╕реЗ рдПрдХ рдЖрд╡рд╢реНрдпрдХ рдЖрдХрд╛рд░ рдХреЗ рдмрдлрд╝рд░реНрд╕ рдХреЛ рдЖрдЙрдЯрдкреБрдЯ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЗрд╕реЗ рдареАрдХ рд╕реЗ рд▓рд╛рдЧреВ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ (рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП рдереЛрдбрд╝рд╛ рдмрдбрд╝рд╛ рдмрдлрд░ рдЕрдЧрд░ рдХреЛрдИ рдЙрдкрдпреБрдХреНрдд рдирд╣реАрдВ рд╣реИ, рд▓реЗрдХрд┐рди originalMemory.Slice(requiredSize) рд╡рд┐рдЦрдВрдбрди рд╕реЗ рдмрдЪрдиреЗ рдХреЗ рд▓рд┐рдП originalMemory.Slice(requiredSize) рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ)ред

рдкреНрд░рджрд░реНрд╢рди


рдирдП рдбреЗрдЯрд╛ рдкреНрд░рдХрд╛рд░реЛрдВ рдХреЗ рдкреНрд░рджрд░реНрд╢рди рдХреЛ рдорд╛рдкрдиреЗ рдХреЗ рд▓рд┐рдП рдореИрдВрдиреЗ рдПрдХ рдкреБрд╕реНрддрдХрд╛рд▓рдп рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХрд╛ рдлреИрд╕рд▓рд╛ рдХрд┐рдпрд╛ рд╣реИ рдЬреЛ рдкрд╣рд▓реЗ рд╕реЗ рд╣реА рдорд╛рдирдХ рдмреЗрдВрдЪрдорд╛рд░реНрдХрдбреЙрдЯрдиреЗрдЯ рдмрди рдЧрдпрд╛ рд╣реИ:


 [Config(typeof(MultipleRuntimesConfig))] public class SpanIndexer { private const int Count = 100; private char[] arrayField; private ArraySegment<char> segment; private string str; [GlobalSetup] public void Setup() { str = new string(Enumerable.Repeat('a', Count).ToArray()); arrayField = str.ToArray(); segment = new ArraySegment<char>(arrayField); } [Benchmark(Baseline = true, OperationsPerInvoke = Count)] public int ArrayIndexer_Get() { var tmp = 0; for (int index = 0, len = arrayField.Length; index < len; index++) { tmp = arrayField[index]; } return tmp; } [Benchmark(OperationsPerInvoke = Count)] public void ArrayIndexer_Set() { for (int index = 0, len = arrayField.Length; index < len; index++) { arrayField[index] = '0'; } } [Benchmark(OperationsPerInvoke = Count)] public int ArraySegmentIndexer_Get() { var tmp = 0; var accessor = (IList<char>)segment; for (int index = 0, len = accessor.Count; index < len; index++) { tmp = accessor[index]; } return tmp; } [Benchmark(OperationsPerInvoke = Count)] public void ArraySegmentIndexer_Set() { var accessor = (IList<char>)segment; for (int index = 0, len = accessor.Count; index < len; index++) { accessor[index] = '0'; } } [Benchmark(OperationsPerInvoke = Count)] public int StringIndexer_Get() { var tmp = 0; for (int index = 0, len = str.Length; index < len; index++) { tmp = str[index]; } return tmp; } [Benchmark(OperationsPerInvoke = Count)] public int SpanArrayIndexer_Get() { var span = arrayField.AsSpan(); var tmp = 0; for (int index = 0, len = span.Length; index < len; index++) { tmp = span[index]; } return tmp; } [Benchmark(OperationsPerInvoke = Count)] public int SpanArraySegmentIndexer_Get() { var span = segment.AsSpan(); var tmp = 0; for (int index = 0, len = span.Length; index < len; index++) { tmp = span[index]; } return tmp; } [Benchmark(OperationsPerInvoke = Count)] public int SpanStringIndexer_Get() { var span = str.AsSpan(); var tmp = 0; for (int index = 0, len = span.Length; index < len; index++) { tmp = span[index]; } return tmp; } [Benchmark(OperationsPerInvoke = Count)] public void SpanArrayIndexer_Set() { var span = arrayField.AsSpan(); for (int index = 0, len = span.Length; index < len; index++) { span[index] = '0'; } } [Benchmark(OperationsPerInvoke = Count)] public void SpanArraySegmentIndexer_Set() { var span = segment.AsSpan(); for (int index = 0, len = span.Length; index < len; index++) { span[index] = '0'; } } } public class MultipleRuntimesConfig : ManualConfig { public MultipleRuntimesConfig() { Add(Job.Default .With(CsProjClassicNetToolchain.Net471) // Span not supported by CLR .WithId(".NET 4.7.1")); Add(Job.Default .With(CsProjCoreToolchain.NetCoreApp20) // Span supported by CLR .WithId(".NET Core 2.0")); Add(Job.Default .With(CsProjCoreToolchain.NetCoreApp21) // Span supported by CLR .WithId(".NET Core 2.1")); Add(Job.Default .With(CsProjCoreToolchain.NetCoreApp22) // Span supported by CLR .WithId(".NET Core 2.2")); } } 

рдЕрдм, рдкрд░рд┐рдгрд╛рдо рджреЗрдЦреЗрдВред


рдкреНрд░рджрд░реНрд╢рди рдЪрд╛рд░реНрдЯ


рдЙрдиреНрд╣реЗрдВ рджреЗрдЦрддреЗ рд╣реБрдП рд╣рдо рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рдЬрд╛рдирдХрд╛рд░реА рдкреНрд░рд╛рдкреНрдд рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ:


  • ArraySegment рднрдпрд╛рдирдХ рд╣реИред рд▓реЗрдХрд┐рди рдЕрдЧрд░ рдЖрдк рдЗрд╕реЗ Span рдореЗрдВ рд▓рдкреЗрдЯрддреЗ рд╣реИрдВ рддреЛ рдЖрдк рдЗрд╕реЗ рдХрдо рднрдпрд╛рдирдХ рдмрдирд╛ рд╕рдХрддреЗ рд╣реИрдВред рдЗрд╕ рдорд╛рдорд▓реЗ рдореЗрдВ, рдкреНрд░рджрд░реНрд╢рди 7 рдЧреБрдирд╛ рдмрдврд╝ рдЬрд╛рдПрдЧрд╛ред
  • рдпрджрд┐ рд╣рдо .NET рдлреНрд░реЗрдорд╡рд░реНрдХ 4.7.1 (рдпрд╣реА рдмрд╛рдд 4.5 рдХреЗ рд▓рд┐рдП рд╣реИ) рдкрд░ рд╡рд┐рдЪрд╛рд░ рдХрд░рддреЗ рд╣реИрдВ, рддреЛ рдбреЗрдЯрд╛ рдмрдлрд╝рд░реНрд╕ рдХреЗ рд╕рд╛рде рдХрд╛рдо рдХрд░рддреЗ рд╕рдордп Span рдХрд╛ рдЙрдкрдпреЛрдЧ рдкреНрд░рджрд░реНрд╢рди рдХреЛ рдХрд╛рдлреА рдХрдо рдХрд░ рджреЗрдЧрд╛ред рдЗрд╕рдореЗрдВ 30-35% рдХреА рдХрдореА рдЖрдПрдЧреАред
  • рд╣рд╛рд▓рд╛рдБрдХрд┐, рдпрджрд┐ рд╣рдо .NET рдХреЛрд░ 2.1+ рдХреЛ рджреЗрдЦрддреЗ рд╣реИрдВ, рддреЛ рдкреНрд░рджрд░реНрд╢рди рд╕рдорд╛рди рд░рд╣рддрд╛ рд╣реИ рдпрд╛ рдпрд╣рд╛рдВ рддрдХ тАЛтАЛрдХрд┐ рдмрдврд╝ рдЬрд╛рддрд╛ рд╣реИ, рдЬреЛ Span рдбреЗрдЯрд╛ рдмрдлрд░ рдХреЗ рдПрдХ рд╣рд┐рд╕реНрд╕реЗ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░ рд╕рдХрддрд╛ рд╣реИ, рд╕рдВрджрд░реНрдн рдмрдирд╛ рд╕рдХрддрд╛ рд╣реИред ArraySegment рдореЗрдВ рд╕рдорд╛рди рдХрд╛рд░реНрдпрдХреНрд╖рдорддрд╛ рдкрд╛рдИ рдЬрд╛ рд╕рдХрддреА рд╣реИ, рд▓реЗрдХрд┐рди рдпрд╣ рдмрд╣реБрдд рдзреАрдореА рдЧрддрд┐ рд╕реЗ рдХрд╛рдо рдХрд░рддреА рд╣реИред

рдЗрд╕ рдкреНрд░рдХрд╛рд░, рд╣рдо рдЗрди рдбреЗрдЯрд╛ рдкреНрд░рдХрд╛рд░реЛрдВ рдХреЗ рдЙрдкрдпреЛрдЧ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рд╕рд░рд▓ рдирд┐рд╖реНрдХрд░реНрд╖ рдирд┐рдХрд╛рд▓ рд╕рдХрддреЗ рд╣реИрдВ:


  • .NET Framework 4.5+ рдФрд░ .NET Core рдЙрдирдХреЗ рдкрд╛рд╕ рдПрдХрдорд╛рддреНрд░ рд▓рд╛рдн рд╣реИ: рд╡реЗ рдореВрд▓ рд╕рд░рдгреА рдХреЗ рд╕рдмрд╕реЗрдЯ рдХреЗ рд╕рд╛рде рдХрд╛рдо рдХрд░рддреЗ рд╕рдордп ArraySegment рддреБрд▓рдирд╛ рдореЗрдВ рддреЗрдЬрд╝ рд╣реИрдВ;
  • .NET Core 2.1+ рдЙрдирдХрд╛ рдЙрдкрдпреЛрдЧ ArraySegment рдФрд░ Slice рдХрд┐рд╕реА рднреА рдореИрдиреБрдЕрд▓ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдкрд░ рдПрдХ рдирд┐рд░реНрд╡рд┐рд╡рд╛рдж рд▓рд╛рдн рджреЗрддрд╛ рд╣реИ;
  • рд╕рднреА рддреАрди рддрд░реАрдХреЗ рдпрдерд╛рд╕рдВрднрд╡ рдЙрддреНрдкрд╛рджрдХ рд╣реИрдВ рдФрд░ рд╕рд░рдгрд┐рдпреЛрдВ рдХреЛ рдПрдХрдЬреБрдЯ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдХрд┐рд╕реА рднреА рдЙрдкрдХрд░рдг рдХреЗ рд╕рд╛рде рдкреНрд░рд╛рдкреНрдд рдирд╣реАрдВ рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИред
    рдпрд╣ рдЕрдзреНрдпрд╛рдп рд░реВрд╕реА рд╕реЗ рд╕рдВрдпреБрдХреНрдд рд░реВрдк рд╕реЗ рд▓реЗрдЦрдХ рджреНрд╡рд╛рд░рд╛ рдФрд░ рдкреЗрд╢реЗрд╡рд░ рдЕрдиреБрд╡рд╛рджрдХреЛрдВ рджреНрд╡рд╛рд░рд╛ рдЕрдиреБрд╡рд╛рджрд┐рдд рдХрд┐рдпрд╛ рдЧрдпрд╛ рдерд╛ ред рдЖрдк рд░реВрд╕реА рдпрд╛ рдЕрдВрдЧреНрд░реЗрдЬреА рд╕реЗ рдХрд┐рд╕реА рдЕрдиреНрдп рднрд╛рд╖рд╛ рдореЗрдВ рдЕрдиреБрд╡рд╛рдж рдХрд░рдиреЗ рдореЗрдВ рд╣рдорд╛рд░реА рдорджрдж рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ, рдореБрдЦреНрдпрддрдГ рдЪреАрдиреА рдпрд╛ рдЬрд░реНрдорди рдореЗрдВред


Source: https://habr.com/ru/post/hi443980/


All Articles