fc2ブログ

とまと あんらいぷ…

エンジニアの活動記録とかつぶやきとか

GitHub
スポンサードリンク

【.NET】指定した範囲で配列をコピーする方法の速度比較【C# 配列】

配列のコピーを行なう時に、範囲を指定する方法がいくつかあるようなので
使用感と実効速度を比較してみた。

System.Array.Copyを使う方法


Array.Copy メソッド

言わずとしれた王道中の王道だと思います。

使い方は

第1引数にコピー元
第2引数に開始index
第3引数にコピー先
第4引数にコピー先の配列に格納する開始位置
第5引数にコピーする要素数

を指定します
Array.Copy( ary1, 2, ary2, 0, 5 );

System.Buffer.BlockCopyを使う方法


少し凝ったやり方です。
Buffer.BlockCopy メソッド
扱いとしては、「配列」というよりはバッファとして考えるのでドットネッターよりもC言語を扱ってた方はとっつきやすいかも。

使い方は

第1引数にコピー元のバッファ
第2引数に第1引数のバイト オフセット
第3引数にコピー先のバッファ
第4引数に第3引数のバイト オフセット
第5引数にコピーするバイト数

注意点は、第5引数はバイト数だということ。
例えばC#でのint型は4byteなので、5要素をコピーしたい場合は4*5で20を指定する必要があります。

Buffer.BlockCopy( ary1, 8, ary2, 0, 20 );


拡張メソッドSkipとTakeメソッドを使う方法


.NET 3.5から利用可能な拡張メソッドです。
参照設定に「System.Core.dll」を指定する必要があります。

配列に対して、すっ飛ばす数と取得する数を指定して、範囲内の要素を取得出来ます。
//Skipで2つの要素を飛ばして、Takeで5つの要素を取得する
int[] ary2 = ary1.Skip( 2 ).Take( 5 ).ToArray();

各処理の実行速度テスト


さて、何を使えばいいのかということで、実行速度のテストを行なってみました。

int型の0-9ある配列を用意し、要素2から5要素を取得する処理を
1000万回実行してみました。
速度計測にはお馴染みのStopwatchクラスを利用しています。



果たして結果は・・・

■Array.Copy
経過時間 575.9902ミリ秒 1回処理あたり平均 0.00005759902ミリ秒

■Buffer.BlockCopy
経過時間 539.7769ミリ秒 1回処理あたり平均 0.00005397769ミリ秒

■Skip.Take
経過時間 3821.5747ミリ秒 1回処理あたり平均 0.00038215747ミリ秒

Skip.Take遅い!!!
繰り返し行なうような処理には向いてないんでしょうね。
Array.CopyとBuffer.BlockCopyはだいたい同じです。
Buffer.BlockCopyの方が7%ぐらい効率がよい程度でしょうか。

というわけで、普段はArray.Copyを使っていれば問題ないと思います。
速度優先が求める時はBuffer.BlockCopyを使えばよいでしょう。
▼この記事を読んだ方は、こんな記事も読んでいます。▼

コメント

Skip+Takeは優秀

遅いのはSkip+Takeではなく、ToArrayです。
測ってみましたが、200以上の配列でToArrayを使わない場合、Skip+Takeの方が速かったです。

ありがとうございます!

Y.Ide さん
書き込みありがとうございます。
.NETのバージョンは何でしょうか?
この記事は2013年の記事で、当時のSkip+Takeはめちゃくちゃ遅かったのです・・・
(たしか .NET 2.0とかだったと思います)

.NETのバージョンで変わるということであれば記事内にその旨記載したいと思います。
よろしくお願いいたします。

  • 2022/05/29(日) 13:33:22 |
  • URL |
  • 管理人 #NwWJJ3y6
  • [ 編集 ]

コメントの投稿


管理者にだけ表示を許可する

トラックバック

トラックバック URL
http://dalmore.blog7.fc2.com/tb.php/57-ac7f42f9
この記事にトラックバックする(FC2ブログユーザー)