62127


# 質問

タイトルの通りですが「効率良く配列の範囲を取り出したい」です。

低レベルのプログラムを書いているため、メモリの範囲読み出しが頻繁に発生しています。  
よって、効率を求めています。

質問内容の「効率良く」いう言葉の意味は以下の通りです。  
\- メモリコピーが少ないもの  
\- メモリアロケーションが少ないもの  
\- CPU使用率が低い物

`Stopwatch`を利用した簡単な処理速度比較のベンチマークは書いたことがあるのですが、  
メモリアロケーション等を考慮したベンチマークはどのように書けばよいか分かりません。

同じ結果が得られるプログラムを以下5つ思いついたのですが、どれが最も効率が良いでしょうか？  
※以下5つ以外でも、効率の良い書き方があれば紹介して頂けると助かります。

[code]

    using System;
    using System.Linq;
    
    namespace Test
    {
      class Program
      {
        static void Main(string[] args)
        {
          var bytes = new byte[] { 1, 2, 3, 4, 5 };
    
          // 方法1. LINQ
          bytes = bytes.Skip(1).Take(3).ToArray();
    
          // 方法2. C#8 Ranges and Indices
          // bytes = bytes[1..4];
    
          // 方法3. Span
          // bytes = bytes.AsSpan(1, 3).ToArray();
    
          // 方法4. Buffer.BlockCopy
          // var tmp = new byte[3];
          // Buffer.BlockCopy(bytes, 1, tmp, 0, 3);
          // bytes = tmp;
    
          // 方法5. Array.Copy
          // var tmp = new byte[3];
          // Array.Copy(bytes, 1, tmp, 0, 3);
          // bytes = tmp;
    
          // 出力: 02-03-04
          Console.WriteLine(BitConverter.ToString(bytes));
        }
      }
    }
    
[/code]


CC BY-SA 4.0
2020-01-10T05:15:44.610
62124
2020-01-10T05:51:53.053
34546
question
c#
効率良く配列の範囲を取り出したい


GCが長さ３の`byte[]`配列を作成するコストが最も高いため、コピー方法の差は微々たるものです。

効率を求めるのであれば、`Span<T>`やポインター等を使い、そもそもコピーしないことを検討すべきです。

なお、方法１ LINQは複雑な処理を簡単に表現することを得意としますが、逆に質問のような低レベルでパフォーマンスを求める処理は不得意です。


CC BY-SA 4.0
2020-01-10T05:51:53.053
62127
2020-01-10T05:51:53.053
4236
62124
answer