.Net Core でプログラムのパフォーマンスを向上させるために ref と Span を使用する方法の実装コード

黄舟
リリース: 2017-05-21 11:11:44
オリジナル
3520 人が閲覧しました

この記事では、プログラムのパフォーマンスを向上させるために .Net Core で ref と Span を使用する簡単な実装コードを主に紹介します。 ref については、多くの学生はすでによく知っています。Ref は

C#

7.0 の言語機能であり、開発者にローカルの 変数参照 を返すメカニズムを提供します。

Span も ref 構文に基づく複雑な

データ型 です。記事の後半では、その使用方法を示す例を示します。 2. Refキーワード
refにしてもoutキーにしても、

C言語

におけるポインタの操作など、理解や操作が比較的難しい言語機能ですが、そのような高度な構文とは何でしょうか?これにはいくつかの副作用が伴いますが、これは大したことではないと思います。また、すべての C# 開発者がこれらの内部動作メカニズムを深く理解する必要があるわけではありません。複雑さに関係なく、人々に自由な選択を提供しているだけだと思います。リスクと柔軟性は決して両立しません。 参照とポインターの類似性を説明するために、いくつかの例を見てみましょう。 もちろん、次の使用法は C# 7.0 以前でも使用できます:

public static void IncrementByRef(ref int x)
{
 x++;
}
public unsafe static void IncrementByPointer(int* x)
{
 (*x)++;
}
ログイン後にコピー
上記の 2 つの

関数

は、それぞれ ref と非安全なポインターを使用します。パラメータ +1 を完成させます。

int i = 30;
IncrementByRef(ref i);
// i = 31
unsafe{
 IncrementByPointer(&i);
}
// i = 32
ログイン後にコピー

C# 7.0で提供される機能は以下のとおりです:

1.ref locals (ローカル変数参照)

この例では、xの値が次の場合のローカル変数iの参照xです。変更すると、変数 i の値も変更されます。

2.ref

returns (戻り値参照)

ref returns は、C# 7 の強力な機能です。次のコードは、その機能を最もよく反映しています。この関数は、特定の int

array

参照を返します。 item:

public static ref int GetArrayRef(int[] items, int index) => ref items[index];
ログイン後にコピー
添字を介して配列内の項目の参照を取得します。参照値が変更されると、それに応じて配列も変更されます。

3. Span

System.Span は、System.Memory.

dl

l アセンブリの下にある .Net Core コアの一部です。現在、この機能は独立していますが、将来 CoreFx に統合される可能性があります 使用方法?次の NuGet パッケージは、.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>
ログイン後にコピー
上では、ref キーワードを使用して提供できる単一値

オブジェクト

を操作するポインター (T*) のような方法を見てきました。基本的に、.NET システムではポインターの操作は適切なイベントとは見なされません。 もちろん、.NET は単一値の参照を安全に操作するための ref を提供します。しかし、単一の値は、「ポインター」を使用するユーザーのニーズのほんの一部にすぎません。ポインターの場合、より一般的な状況は、連続したメモリ空間で一連の「要素」を操作する場合です。 スパンは、既知の長さとタイプの連続したメモリ ブロックとして表されます。メモリ領域ポインタへの安全なアクセスを提供するという点で、多くの点で T[] または ArraySegment と非常に似ています。実際、これは .NET の操作 (void*) ポインターの抽象化であると私は理解しています。C/C++ に詳しい開発者は、これが何を意味するのかをよく理解する必要があります。

スパン機能は次のとおりです: •配列、アンマネージ ポインタ、スタック ポインタ、固定または固定された管理データ、および値の内部領域への参照を含む、すべての連続メモリ空間の型システムを抽象化します

• CLR 標準のオブジェクト型と値型をサポートします

•ジェネリクスをサポートします

•独自に管理および解放する必要があるポインターとは異なり、GC をサポートします

構文的にも意味的にも ref: に関連する Span の定義を見てみましょう。

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 {...} }
 ...
}
ログイン後にコピー
次に、直感的な例を使用して Span の使用シナリオを説明します。例として、文字インターセプトと文字変換 ​​(整数への変換) を取り上げます。 "content-length:123", 123 を整数に変換するには、まず Substr

して数値と関係のない文字列を切り詰めます。変換コードは次のとおりです。

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");
ログイン後にコピー

理由 この例では、文字列を操作するたびに、int.Parse を実行する際に、新しい文字列オブジェクトが繰り返し生成されるという例を示します。多数の操作を実行すると、GC 圧力が損傷する可能性があります。

このアルゴリズムを実装するには Span を使用します:

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");
ログイン後にコピー

这里将string转换为int的算法利用ReadonlySpan实现,这也是Span的典型使用场景,官方给的场景也是如些,Span适用于多次复用操作连续内存的场景。

转换代码如下:

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(&#39;-&#39;)){
   sign = -1; index = 1;
  }
  for (int idx = index; idx < rspan.Length; idx++){
   char c = rspan[idx];
   num = (c - &#39;0&#39;) + num * 10;
  }
  return num * sign;
 }
}
ログイン後にコピー

四、最后

上述两段代码100000次调用的时间如下:

String Substring Convert:
  Time Elapsed: 18ms
ReadOnlySpan Convert:
  Time Elapsed: 4ms
ログイン後にコピー

目前Span的相关支持还够,它只是最基础架构,之后CoreFx会对很多API使用Span进行重构和实现。可见.Net Core的性能日后会越来越强大。

以上が.Net Core でプログラムのパフォーマンスを向上させるために ref と Span を使用する方法の実装コードの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

関連ラベル:
ソース:php.cn
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート