はじめに
Qiita 記事は初投稿となります。いろいろとおかしな点もあるかもしれません。
さて、TwitterでC#における OrderByとSortのパフォーマンスの違いの話になって、自分もどれくらいの差があるのか把握していなかったので、検証して、せっかくなので記事に残すことにしました。
#環境
この記事では、以下の環境を使用しました。
Windows 10 Home
Intel Core i5 6400T
.NET Framework 4.6.1
Visual Studio 2019 Debug環境
#検証方法
元の配列は、0から(10^6 - 1)を昇順に並べた、100万要素の配列とする。
Array.Sort(array)
List<T>.Sort()
enumerable.OrderBy(x => x)
それぞれについて、ソートを10回行う。
- 以下に記載してある時間は「ミリ秒単位」で「ソート10回分」です。(1回あたりは10で割ってください。)
##ランダム順の配列を並び替え
以下の操作を10回行い、ソート10回にかかった時間の平均値・最大値・最小値を計算します。
- 元の配列をランダム順に並び替える。
- それぞれのソート関数でソートを実行する。
###結果
| |Array.Sort|List.Sort|OrderBy|
|:-----:|:---------|:--------|:------|
|Max|1721ms|1448ms|5428ms|
|Min|1307ms|1301ms|5177ms|
|Ave|1375.5ms|1347.7ms|5306.7ms|
ランダム順では、List.Sort
が Array.Sort
よりわずかに早く、OrderBy
はそれらより4倍近く遅い結果となりました。
##昇順・降順の配列を並び替え
以下の操作それぞれで、ソート10回にかかった時間を計算します。
- 昇順となっている(すでにソートされている)配列に対してソートを実行する。
- 降順となっている配列に対してソートを実行する。
###結果
| |Array.Sort|List.Sort|OrderBy|
|:-----:|:---------|:--------|:------|
|昇順|175ms|184ms|2608ms|
|降順|368ms|313ms|1923ms|
昇順配列におけるソートでは、 Array.Sort
が List.Sort
よりわずかに早く、 OrderBy
はそれらより15倍近く(!)遅い結果となりました。
降順配列におけるソートでは、 List.Sort
が Array.Sort
より少し早く、 OrderBy
はそれらより6倍近く遅い結果となりました。
それぞれの関数別にみると、
Array.Sort
では、昇順配列におけるソートが降順配列におけるソートより約2倍早く、ランダム配列におけるソートより約8倍早い。
List.Sort
では、昇順配列におけるソートが降順配列におけるソートより約1.7倍早く、ランダム配列におけるソートより約7.3倍早い。
OrderBy
では、昇順配列におけるソートが降順配列におけるソートより約1.3倍遅く、ランダム配列におけるソートより約2倍早いという結果になりました。
#まとめ
今回の検証に使用したコードは、 Gistに載せています。
数値や文字列などの、オブジェクト自体の並び替えには、絶対に Array.Sort
や List<T>.Sort()
を使いましょう!! (特に私は競技プログラミングをやっていて、数百ミリ秒でも早いほうがいいため、今後はSortを使うことをより意識しようと思います。ソートが原因でTLEはくらいたくない!!)
今回は検証していませんが、オブジェクトのプロパティを指定した並び替えでも、objects.OrderBy(x => x.Target);
とするよりも、ToArray()
→ Array.Sort(objectsArray, (a, b) => a.Target.CompareTo(b.Target);
としたほうが高速だと思います。
OrderBy
は、IEnumerable<T>
を対象に並び替えができるようになっているため、遅い実装になっているんですかね…。
- もしかしたら遅延評価の問題などで、
OrderBy
のほうが高速になることがあるかもしれません。 (特にEnumerateFiles
などで外部にアクセスするとき)
この記事について、ご意見やご指摘などがありましたら、記事のコメント等へお願いいたします。