Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

YouTube videos are no longer supported on SlideShare

View original on YouTube

A (brief) overview of Span<T> Slide 2
A (brief) overview of Span<T> Slide 3
Upcoming SlideShare
What to Upload to SlideShare
What to Upload to SlideShare
Loading in …3
×
1 of 27

A (brief) overview of Span<T>

1

Share

Download to read offline

“System.Span<T> is a new value type at the heart of .NET [that] enables the representation of contiguous regions of arbitrary memory”.

Related Books

Free with a 30 day trial from Scribd

See all

Related Audiobooks

Free with a 30 day trial from Scribd

See all

A (brief) overview of Span<T>

  1. 1. A (brief) overview of Span<T> (and ReadOnlySpan<T> and Memory<T> and ReadOnlyMemory<T>) DAVID WENGIER @davidwengier
  2. 2. What is Span<T>? - Stephen Toub, MSDN Magazine, January 2018 https://msdn.microsoft.com/en-us/magazine/mt814808 “System.Span<T> is a new value type at the heart of .NET [that] enables the representation of contiguous regions of arbitrary memory”
  3. 3. What is Span<T>? • struct • Part of System.Memory, available on Nuget • Currently at rc1 version (prerelease) • .NET Standard 1.0 so can be used in .NET 4.5+ • C# 7.2-ish “System.Span<T> is a new value type at the heart of .NET [that] enables the representation of contiguous regions of arbitrary memory”
  4. 4. What is Span<T>? • High performance, low (no) overhead • Framework, CLR, JIT and GC support • Provides memory and type safety • Avoids the need for unsafe code “System.Span<T> is a new value type at the heart of .NET [that] enables the representation of contiguous regions of arbitrary memory”
  5. 5. What is Span<T>? • Native/unmanaged memory (P/Invoke) • Managed memory (.NET types) • Stack memory (stackalloc) “System.Span<T> is a new value type at the heart of .NET [that] enables the representation of contiguous regions of arbitrary memory”
  6. 6. What is Span<T>? • Think of it like having an array to access raw memory
  7. 7. var arr = new byte[10]; Span<byte> bytes = arr; bytes[0] = 42; Assert.True(arr[0] == 42); Span<byte> slice = bytes.Slice(4, 3); slice[0] = 43; Assert.True(bytes[4] == 43); Assert.True(arr[4] == 43); slice[5] = 44; // IndexOutOfRangeException
  8. 8. HeapStack 0x01 0x02 0x03 0x04 0x05 0x06 string plate = “YGG871”; plate = plate.Substring(3); int num = int.Parse(plate); plate 0x01 “YGG871” plate 0x02 “871” num 871
  9. 9. HeapStack 0x01 0x02 0x03 0x04 0x05 0x06 string plate = “YGG871”; ReadOnlySpan<char> s = plate.AsSpan(); s = s.Slice(3); int num = int.Parse(s); plate 0x01 “YGG871” 0x01 0 6 3 num 871 span offset pointer length .NET Framework 4.5+ - slow span
  10. 10. HeapStack 0x01 0x02 0x03 0x04 0x05 0x06 string plate = “YGG871”; ReadOnlySpan<char> s = plate.AsSpan(); s = s.Slice(3); int num = int.Parse(s); plate 0x01 “YGG871” 0x01+3 3 num 871 ref span length pointer .NET Core 2.0+ – fast span
  11. 11. * From Adam Sitnik - http://adamsitnik.com/Span/ Method Job Mean StdDev SpanIndexer_G et .NET 4.6 0.6054 ns 0.0007 ns SpanIndexer_G et .NET Core 1.1 0.6047 ns 0.0008 ns SpanIndexer_G et .NET Core 2.0 0.5333 ns 0.0006 ns SpanIndexer_S et .NET 4.6 0.6059 ns 0.0007 ns SpanIndexer_S et .NET Core 1.1 0.6042 ns 0.0002 ns SpanIndexer_S et .NET Core 2.0 0.5205 ns 0.0003 n
  12. 12. Method String Length Mean StdDev Scaled Gen 0 Allocated * Substring 10 8.277 ns 0.1938 ns 4.54 0.0191 40 B Slice 10 1.822 ns 0.0383 ns 1.00 - 0 B Substring 1000 85.518 ns 1.3474 ns 47.22 0.4919 1032 B Slice 1000 1.811 ns 0.0205 ns 1.00 - 0 B * Not including original string
  13. 13. Framework Support https://github.com/dotnet/corefx/blob/master/src/Common/src/CoreLib/System/Int32.cs
  14. 14. Framework Support
  15. 15. Framework Support // RandomStringLoop var stringChars = new char[Length]; for (int i = 0; i < stringChars.Length; i++) { stringChars[i] = (char)(random.Next(0, 10) + '0'); } return new string(stringChars); // RandomStringEnumerable return new string(Enumerable.Repeat("", Length) .Select(s => (char)(random.Next(0, 10) + '0')).ToArray()); // RandomStringSpan return string.Create(Length, random, (Span<char> chars, Random r) => { for (int i = 0; i < chars.Length; i++) { chars[i] = (char)(r.Next(0, 10) + '0'); } });
  16. 16. Method Length Mean Scaled Allocated RandomStringSpan 10 150.29 ns 1.00 48 B RandomStringLoop 10 156.16 ns 1.04 96 B RandomStringEnumerable 10 340.26 ns 2.27 192 B RandomStringSpan 100 1,314.91 ns 1.00 232 B RandomStringLoop 100 1,361.57 ns 1.04 456 B RandomStringEnumerable 100 2,140.91 ns 1.63 552 B RandomStringSpan 1000 12,461.32 ns 1.00 2032 B RandomStringLoop 1000 14,073.65 ns 1.13 4056 B RandomStringEnumerable 1000 20,354.63 ns 1.63 4152 B
  17. 17. When do mere mortals use it? public static bool ContainsCapitalLetters(string s) { for (int i = 0; i < s.Length; i++) { if (char.IsUpper(s[i])) { return true; } } return false; } public static int Sum(int[] a) { int sum = 0; for (int i = 0; i < a.Length; i++) { sum += a[i]; } return sum; }
  18. 18. When do mere mortals use it? public static bool ContainsCapitalLetters(ReadOnlySpan<char> s) { for (int i = 0; i < s.Length; i++) { if (char.IsUpper(s[i])) { return true; } } return false; } public static int Sum(ReadOnlySpan<int> a) { int sum = 0; for (int i = 0; i < a.Length; i++) { sum += a[i]; } return sum; }
  19. 19. Limitations • Can only live on the stack • Implemented as a ref struct • Can only be contained by ref structs
  20. 20. ref structs Structs that can exist only on the stack. New in C# 7.2 • Can’t implement interfaces • Can’t be used as generic type arguments • Can’t be boxed to object • Can’t be passed in to - or used in places inside - of async methods, iterators, nested functions or query expressions
  21. 21. async Task DoSomethingAsync(Span<byte> buffer) { buffer[0] = 0; await Something(); buffer[0] = 1; } async Task DoSomethingAsync(Span<byte> buffer) { SomethingClass cl = new SomethingClass() cl.buffer = buffer; cl.StartSomething(); } private class SomethingClass { public Span<byte> buffer; // illegal public void Start_Something() { buffer[0] = 0; DoMagicAsyncStuff().ContinueWith(End_Something); } public void End_Something() { buffer[0] = 1; } }
  22. 22. Memory<T> • “Normal” struct • Not as performant as Span • Can be used in more places than Span (ie, doesn’t have the limitations)
  23. 23. Memory<T> async Task DoSomethingAsync(Span<byte> buffer) { buffer[0] = 0; await Something(); // Bang! buffer[0] = 1; } async Task DoSomethingAsync(Memory<byte> buffer) { buffer.Span[0] = 0; await Something(); // Totally fine buffer.Span[0] = 1; }
  24. 24. Memory<T> public struct Memory<T> { private int _offset; private int _length; private int _pointer; private byte[] _data; // really OwnedMemory<T> public Span<T> Span => new Span<T>(_data, _pointer, _offset, _length); } * Not real
  25. 25. TechEmpower Plaintext Round 14 Round 15
  26. 26. DAVID WENGIER @davidwengier Thank you! Questions?

×