The highlight of .net core 2.1 is performance, and the two most important categories are span and memory. Here is a brief introduction to the use of these two categories.
What is Span<T>
Span<T> is a new type of value. It represents a continuous area, which is usually associated with an array, representing a portion of memory in the array.
var arr = new byte[10]; Span<byte> bytes = arr;
You can also take part of the array:
var bytes = new Span<byte>(arr, 3, 5);
At first glance, span<T> and ArraySegment<T> look very similar, but span is much more powerful. It can not only be used to separate arrays, but also reference data on the stack.
Span<byte> bytes = stackalloc byte[2];
You can also reference pointer data.
Span<byte> bytes; unsafe { bytes = new Span<byte>((byte*)ptr, 1); }
In addition, span also supports the concept of reinterpret_cast, that is, you can cast Span<byte> to Span<int>, in conjunction withMemoryMarshalWhen using class, span<T> can replace pointers most of the time.
In addition to being more powerful, span has also received more support in the bcl library. Most functions that support arrays can now basically directly support span, such as:
var inputSpan = (); int first = ((3, 5));
In this function, the function can directly support span, and since it does not generate substring, it performs better than the method using substring.
In addition, the system also supports implicit conversion from array type to span, and also provides the display extension method of AsSpan to facilitate converting array type to span.
In addition to being powerful, the performance of span is also very high. Operations on spans are basically as high as accessing arrays, without the need to calculate the beginning of the pointer and its starting offset, because the "reference" field itself has encapsulated both. In contrast, ArraySegment<T> has separate offset fields, which increases the cost of indexing and data delivery operations.
What is Memory<T>
Although Span<T> is powerful and easy to use, it can only exist on the stack, not on the heap. The main reasons are as follows:
- A span contains "references" fields (such as the beginning of an array), which are called "internal pointers". For garbage collectors at the .NET runtime, tracking these pointers is a relatively expensive operation. Therefore, the runtime constrains these references to exist only on the stack, because it implicitly specifies the lower limit of the number of internal pointers that can exist.
- Read and write operations performed on Span are not atomic operations. There is a risk of "tearing" if multiple threads perform read and write operations on Span's fields on the heap at the same time.
This limitation determines that Span cannot be boxed, and in turn, cannot be used with existing reflection call APIs, nor as a generic parameter.
For most synchronous processing functions, this does not have much impact, but because span<T> cannot be stored to the heap, it cannot be used in an asynchronous context. To solve this problem, .net introduced a new type of Memory<T>.
Memory and span are used in similar ways.
var arr = new byte[10]; var bytes = new Memory<byte>(arr, 3, 5);
The difference is that Memory<T> is a structure that is not similar to references and can exist on the heap. The .net bcl library also provides good support for memory, such as memory<byte> can be directly supported as a parameter.
In addition, you can also create a span pointing to the Memory from the Span property of the Memory, so that the powerful functions of the span can be used.
Reference article:
C# - Span Full Introduction: Exploring the Important Components of .NET
This is all about this article about the Span<T> class and Memory<T> class in .net. I hope it will be helpful to everyone's learning and I hope everyone will support me more.