##SeqとListとArrayのパフォーマンス比較
気になったので実験してみた。
単純な生成コストと、インデックスアクセスの速度を比較。
速度はSeq > Array >> Listのようである。
@vain0x さんにコメント欄で指摘いただいた通り、計測コードの書き方が間違ってたみたい。
再計測の結果、速度はArray >>> List > Seq となった。
※数は公平にするために10^8のまま
###dotnetcore2.1で計測
Method | Mean | Error | StdDev | Median |
---|---|---|---|---|
ABench(Seq) | 182,376.5 ns | 5,210.94 ns | 14,088.1 ns | 175,500.0 ns |
BBench(List) | 214,139.7 ns | 5,123.56 ns | 12,759.4 ns | 214,900.0 ns |
CBench(Array) | 766.0 ns | 68.92 ns | 199.9 ns | 800.0 ns |
###dotnetcore3.1で計測
Method | Mean | Error | StdDev | Median |
---|---|---|---|---|
ABench(Seq) | 243.788 us | 14.0499 us | 41.206 us | 230.800 us |
BBench(List) | 228.499 us | 5.4869 us | 15.743 us | 226.600 us |
CBench(Array) | 2.068 us | 0.6108 us | 1.672 us | 1.300 us |
頂いたコメントとデータの傾向が違うなと思ってたら、dotnetのバージョンの差異のようだ。
3.1にするとだいたい近い結果になった。
サマリは単位がマイクロとナノでずれてるけど、
揃えて考えると2.1より3.1の方が全体的に遅くなってる感がある。
走行時間も増えてるし、なんでやろねぇ。
###感想
ベンチ走らせるのに約35分程かかった。
途中で気づいたけど、もっとまともなベンチ名にするべきだったね...
まあListはデータ構造的にアクセス速度遅くて当然として。
当初予想では、Seqはメモリ上一個しか存在しないらしいと聞いて
Arrayよりも生成コストかからず爆速になるのかなーって思ってた。
Arrayだとインスタンス2個とも100,000,000回ループ回すけど
Seqはインスタンス1個分だけ生成したら、2個目にはインスタンス1のアドレスが代入されるのかなーと。
内包表記を2個呼び出してるのはこれを試そうと思ったから。
実際見てるとリストよりも遅いので、そんなに早い訳ではないらしい。
##検証コードと結果
###テストコード(修正版)
module Program
open BenchmarkDotNet
open BenchmarkDotNet.Attributes
let buildCardSeq = seq { 1..100000000 }
let buildCardList = [ 1..100000000 ]
let buildCardArray = [| 1..100000000 |]
let A () =
let bs1 = buildCardSeq
let bs2 = buildCardSeq
bs1 |> Seq.item 56789
let B () =
let bl1 = buildCardList
let bl2 = buildCardList
bl1 |> List.item 56789
let C () =
let ba1 = buildCardArray
let ba2 = buildCardArray
ba1 |> Array.item 56789
type Benchmarks() =
[<Benchmark>]
member x.ABench() =
A()
[<Benchmark>]
member x.BBench() =
B()
[<Benchmark>]
member x.CBench() =
C()
[<EntryPoint>]
let main _ =
let _summary = Running.BenchmarkRunner.Run<Benchmarks>()
0
###サマリ(dotnetcore3.1)
// * Summary *
BenchmarkDotNet=v0.12.0, OS=Windows 10.0.18363
Intel Core i7-4650U CPU 1.70GHz (Haswell), 1 CPU, 4 logical and 2 physical cores
.NET Core SDK=3.1.101
[Host] : .NET Core 3.1.1 (CoreCLR 4.700.19.60701, CoreFX 4.700.19.60801), X64 RyuJIT DEBUG
DefaultJob : .NET Core 3.1.1 (CoreCLR 4.700.19.60701, CoreFX 4.700.19.60801), X64 RyuJIT
| Method | Mean | Error | StdDev | Median |
|------- |-----------:|-----------:|----------:|-----------:|
| ABench | 243.788 us | 14.0499 us | 41.206 us | 230.800 us |
| BBench | 228.499 us | 5.4869 us | 15.743 us | 226.600 us |
| CBench | 2.068 us | 0.6108 us | 1.672 us | 1.300 us |
// * Warnings *
MinIterationTime
Benchmarks.ABench: Default -> The minimum observed iteration time is 200.2000 us which is very small. It's recommended to increase it.
Benchmarks.BBench: Default -> The minimum observed iteration time is 200.9000 us which is very small. It's recommended to increase it.
Benchmarks.CBench: Default -> The minimum observed iteration time is 900.0000 ns which is very small. It's recommended to increase it.
MultimodalDistribution
Benchmarks.BBench: Default -> It seems that the distribution can have several modes (mValue = 2.86)
// * Hints *
Outliers
Benchmarks.ABench: Default -> 1 outlier was removed (405.80 us)
Benchmarks.BBench: Default -> 5 outliers were removed (289.60 us..393.00 us)
Benchmarks.CBench: Default -> 13 outliers were removed (7.20 us..11.80 us)
// * Legends *
Mean : Arithmetic mean of all measurements
Error : Half of 99.9% confidence interval
StdDev : Standard deviation of all measurements
Median : Value separating the higher half of all measurements (50th percentile)
1 us : 1 Microsecond (0.000001 sec)
// ***** BenchmarkRunner: End *****
// ** Remained 0 benchmark(s) to run **
Run time: 00:37:52 (2272.5 sec), executed benchmarks: 3
Global total time: 00:37:58 (2278.54 sec), executed benchmarks: 3
// * Artifacts cleanup *
###サマリ(dotnetcore2.1)
// * Summary *
BenchmarkDotNet=v0.12.0, OS=Windows 10.0.18363
Intel Core i7-4650U CPU 1.70GHz (Haswell), 1 CPU, 4 logical and 2 physical cores
.NET Core SDK=3.1.101
[Host] : .NET Core 2.1.9 (CoreCLR 4.6.27414.06, CoreFX 4.6.27415.01), X64 RyuJIT DEBUG
DefaultJob : .NET Core 2.1.9 (CoreCLR 4.6.27414.06, CoreFX 4.6.27415.01), X64 RyuJIT
| Method | Mean | Error | StdDev | Median |
|------- |-------------:|------------:|------------:|-------------:|
| ABench | 182,376.5 ns | 5,210.94 ns | 14,088.1 ns | 175,500.0 ns |
| BBench | 214,139.7 ns | 5,123.56 ns | 12,759.4 ns | 214,900.0 ns |
| CBench | 766.0 ns | 68.92 ns | 199.9 ns | 800.0 ns |
// * Warnings *
MinIterationTime
Benchmarks.ABench: Default -> The minimum observed iteration time is 175.1000 us which is very small. It's recommended to increase it.
Benchmarks.BBench: Default -> The minimum observed iteration time is 192.3000 us which is very small. It's recommended to increase it.
Benchmarks.CBench: Default -> The minimum observed iteration time is 400.0000 ns which is very small. It's recommended to increase it.
MultimodalDistribution
Benchmarks.BBench: Default -> It seems that the distribution can have several modes (mValue = 3.03)
// * Hints *
Outliers
Benchmarks.ABench: Default -> 15 outliers were removed (245.20 us..340.60 us)
Benchmarks.BBench: Default -> 12 outliers were removed (258.70 us..370.60 us)
Benchmarks.CBench: Default -> 3 outliers were removed (1.60 us..2.10 us)
// * Legends *
Mean : Arithmetic mean of all measurements
Error : Half of 99.9% confidence interval
StdDev : Standard deviation of all measurements
Median : Value separating the higher half of all measurements (50th percentile)
1 ns : 1 Nanosecond (0.000000001 sec)
// ***** BenchmarkRunner: End *****
// ** Remained 0 benchmark(s) to run **
Run time: 00:34:56 (2096.23 sec), executed benchmarks: 3
Global total time: 00:35:05 (2105.93 sec), executed benchmarks: 3
// * Artifacts cleanup *
##修正前
今後の自分のために残しておく
###テストコード(修正前)
module Program
open BenchmarkDotNet
open BenchmarkDotNet.Attributes
let buildCardSeq = seq { 1..100000000 }
let buildCardList = [ 1..100000000 ]
let buildCardArray = [| 1..100000000 |]
let A =
let bs1 = buildCardSeq
let bs2 = buildCardSeq
bs1 |> Seq.item 56789
let B =
let bl1 = buildCardList
let bl2 = buildCardList
bl1 |> List.item 56789
let C =
let ba1 = buildCardArray
let ba2 = buildCardArray
ba1 |> Array.item 56789
type Benchmarks() =
[<Benchmark>]
member x.ABench() =
A
[<Benchmark>]
member x.BBench() =
B
[<Benchmark>]
member x.CBench() =
C
[<EntryPoint>]
let main _ =
let _summary = Running.BenchmarkRunner.Run<Benchmarks>()
0
###サマリ(修正前)
// * Summary *
BenchmarkDotNet=v0.12.0, OS=Windows 10.0.18363
Intel Core i7-4650U CPU 1.70GHz (Haswell), 1 CPU, 4 logical and 2 physical cores
.NET Core SDK=3.1.101
[Host] : .NET Core 2.1.9 (CoreCLR 4.6.27414.06, CoreFX 4.6.27415.01), X64 RyuJIT DEBUG
DefaultJob : .NET Core 2.1.9 (CoreCLR 4.6.27414.06, CoreFX 4.6.27415.01), X64 RyuJIT
| Method | Mean | Error | StdDev | Median |
|------- |-------------:|------------:|------------:|-------------:|
| ABench | 182,376.5 ns | 5,210.94 ns | 14,088.1 ns | 175,500.0 ns |
| BBench | 214,139.7 ns | 5,123.56 ns | 12,759.4 ns | 214,900.0 ns |
| CBench | 766.0 ns | 68.92 ns | 199.9 ns | 800.0 ns |
// * Warnings *
MinIterationTime
Benchmarks.ABench: Default -> The minimum observed iteration time is 175.1000 us which is very small. It's recommended to increase it.
Benchmarks.BBench: Default -> The minimum observed iteration time is 192.3000 us which is very small. It's recommended to increase it.
Benchmarks.CBench: Default -> The minimum observed iteration time is 400.0000 ns which is very small. It's recommended to increase it.
MultimodalDistribution
Benchmarks.BBench: Default -> It seems that the distribution can have several modes (mValue = 3.03)
// * Hints *
Outliers
Benchmarks.ABench: Default -> 15 outliers were removed (245.20 us..340.60 us)
Benchmarks.BBench: Default -> 12 outliers were removed (258.70 us..370.60 us)
Benchmarks.CBench: Default -> 3 outliers were removed (1.60 us..2.10 us)
// * Legends *
Mean : Arithmetic mean of all measurements
Error : Half of 99.9% confidence interval
StdDev : Standard deviation of all measurements
Median : Value separating the higher half of all measurements (50th percentile)
1 ns : 1 Nanosecond (0.000000001 sec)
// ***** BenchmarkRunner: End *****
// ** Remained 0 benchmark(s) to run **
Run time: 00:34:56 (2096.23 sec), executed benchmarks: 3
Global total time: 00:35:05 (2105.93 sec), executed benchmarks: 3
// * Artifacts cleanup *