Code Analysis: Improving program performance with ref and span<t> in. Net Core

Source: Internet
Author: User
This article focuses on the simple implementation code in. Net core that uses ref and span<t> to improve program performance, and the friends you need can refer to the following





First, preface



In fact, when it comes to ref, a lot of students know about it, ref is a language feature of C # 7.0, which provides a mechanism for developers to return local variable references and value references.
Span is also a complex data type based on the ref syntax, and in the latter part of the article, I'll have an example of how to use it.



Second, ref keyword



Whether it is ref or out key, is a more difficult to understand and manipulate the language features, such as the C language in the manipulation of pointers, such high-level syntax is always what brings some side effects, but I do not think this is what, and not every C # developers have to have a deep understanding of these internal operating mechanisms, I feel that whatever complex thing is just a free choice for people, risk and flexibility are never compatible.



Let's look at a few examples to illustrate the similarity of the reference to the pointer, and of course the following usage is available before C # 7.0:



public static void IncrementByRef(ref int x)

{

 x++;

}

public unsafe static void IncrementByPointer(int* x)

{

 (*x)++;

}

The above two functions use ref and non-secure pointers to complete parameter +1, respectively.


int i = 30;

IncrementByRef(ref i);

// i = 31

unsafe{

 IncrementByPointer(&i);

}

// i = 32



The following are the features that C # 7.0 provides:



1.ref locals (referencing local variables)


int i = 42;

ref var x = ref i;

x = x + 1;

// i = 43



In this example, a reference to the local I variable is x, and the value of the I variable changes when the value of x is changed.



2.ref Returns (return value reference)



Ref returns is a powerful feature in C # 7, and the following code is the best embodiment of its characteristics, which provides a reference to an item in an int array:






public static ref int Getarrayref (int[] items, int index) = ref Items[index];


When you change the reference value by using the subscript to obtain a reference to the items in the array, the array changes as well.



Three, Span



System.span is part of the. Net core Core, under the System.Memory.dll assembly. Currently this feature is independent and may be integrated into the COREFX in the future;



How to use it? The following NuGet packages are referenced under the project created by the. Net Core 2.0 SDK:


<ItemGroup>

<PackageReference Include="System.Memory" Version="4.4.0-preview1-25305-02" />

<PackageReference Include="System.Runtime.CompilerServices.Unsafe" Version="4.4.0-preview1-25305-02" />

</ItemGroup>



In the above we see the way of manipulating a single value object using a pointer (t*) that can be supplied with the REF keyword. Basically in. NET system operation pointers are not considered a good event, of course. NET provides us with a safe operation of a single value reference to ref. But a single value is just a small part of the user's need for a "pointer"; for pointers, it is more common to manipulate "elements" in a series of contiguous memory spaces.



Span is expressed as a contiguous block of memory of a known length and type. In many ways it is very similar to t[] or arraysegment, which provides the ability to access the memory area pointers securely. Actually I understand it will be more. NET operation (void*) pointer abstraction, familiarity with C + + developers should be more aware of what this means.



The features of span are as follows:



• A type system that abstracts all contiguous memory spaces, including: arrays, unmanaged pointers, stack pointers, fixed or pinned managed data, and references to values inner areas
• Supports CLR standard object types and value types
• Supports generics
• Support for GC, unlike pointers need to manage release



Here's a definition of span, which has a syntactic and semantic connection to ref:



public struct Span<T> {

 ref T _reference;

 int _length;

 public ref T this[int index] { get {...} }

 ...

}

public struct ReadOnlySpan<T> {

 ref T _reference;

 int _length;

 public T this[int index] { get {...} }

 ...

}



Next, I'll use a visual example to illustrate the usage of span, as an example of character interception and character conversion (converting to Integer):



If a string isstring content = "content-length:123",to be converted to convert 123 to an integer, the usual practice is to first substring the string that is not related to the numeric character, and the conversion code is as follows:



string content = "content-length:123";

Stopwatch watch1 = new Stopwatch();

watch1.Start();

for (int j = 0; j < 100000; j++)

{

 int.Parse(content.Substring(15));

}

watch1.Stop();

Console.WriteLine("\tTime Elapsed:\t" + watch1.ElapsedMilliseconds.ToString("N0") + "ms");



Why use this example, this is a typical substring usage scenario where a string is generated each time a new string object is created, of course, not just substring, in Int. Parse when the string object is repeated, if a large number of operations will put pressure on the GC.



Use span to implement this algorithm:



string content = "content-length:123";

ReadOnlySpan<char> span = content.ToCharArray(); 

span.Slice(15).ParseToInt();

watch.Start();

for (int j = 0; j < 100000; j++)

{

 int icb = span.Slice(15).ParseToInt();

}

watch.Stop();

Console.WriteLine("\tTime Elapsed:\t" + watch.ElapsedMilliseconds.ToString("N0") + "ms");



Here the algorithm of converting string to int is implemented using Readonlyspan, which is also a typical usage scenario for spans, as is the case with the official scenario, where span is suitable for multiple multiplexed operations of contiguous memory.



The conversion code is as follows:



public static class ReadonlySpanxtension

{

 public static int ParseToInt(this ReadOnlySpan<char> rspan)

 {

  Int16 sign = 1;

  int num = 0;

  UInt16 index = 0;

  if (rspan[0].Equals('-')){

   sign = -1; index = 1;

  }

  for (int idx = index; idx < rspan.Length; idx++){

   char c = rspan[idx];

   num = (c - '0') + num * 10;

  }

  return num * sign;

 }

}



Iv. final



The time of the above two code 100,000 calls is as follows:



String Substring Convert:

  Time Elapsed: 18ms

ReadOnlySpan Convert:

  Time Elapsed: 4ms



The current support for span is enough, it's just the most basic architecture, and then Corefx will refactor and implement many APIs using span. Visible. Net core performance will become more powerful in the future.


Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.