Linq Count(
)メソッドは、List<>.Count
またはArray.Length
より速くまたは遅くなりますか?Linq Count()はList.CountまたはArray.Lengthより高速か、遅いのですか?
答えて
一般的に遅い。 LINQのカウントは通常O(N)
であり、List.Count
とArray.Length
はともにO(1)
であることが保証されています。
ただし、IList<T>
またはICollection<T>
などの特定のインターフェイスタイプにキャストすると、LINQは特別な場合にIEnumerable<T>
パラメータを使用します。その後、そのCountメソッドを使用して実際の操作を実行します(Count()
)。したがって、それはO(1)
に戻るでしょう。しかし、あなたはまだキャストとインターフェイスコールのわずかなオーバーヘッドを支払うだけです。
@Marc、私はそのカバエを付け加えました。 – JaredPar
私はよく分かりませんが、List.Count()がIQueryable上で実行されるとselect count(*)sqlコマンドが実行されると思います。 List.Countを実行すると、すべての項目を列挙してカウントを返します。後者の場合、List.Count()はほとんどの場合、より高速になります。 – Jose
@Jared、Marcsの答えはより正確です。チェックはICollection
ICollectionまたはIList(ArrayListやListなど)のいずれかでLinq.Count()を呼び出すと、Countプロパティの値が返されると思います。したがって、パフォーマンスは単純なコレクションでほぼ同じになります。
ArrayListはIEnumerable
.Count
を用いICollection<T>
ためEnumerable.Count()
方法チェック、 - そうアレイ及びリストの場合には、(間接のちょうど余分レベル)はるかに非効率的ではありません。
実際には、2層のインダイレクションを持つ配列では、私の答えをご覧ください:p –
私はそれがリストに依存していると言います。 dbのどこかのテーブルであるIQueryableの場合、Count()はより速く、すべてのオブジェクトをロードする必要がないため、より高速にになります。しかし、リストがメモリ内にあれば、Countプロパティは同じではないにしても高速になると思います。
マークは正しい答えを持っていますが、悪魔は詳細です。私のマシン上で
:約100倍高速.Countよりも(ある.LENGTHアレイの場合
- )
- リストの.Countが(.Countよりも約10倍高速である) - 注:私は希望すべての実装と同様のパフォーマンスを期待する
IList<T>
.Lengthには1回の操作しか含まれていないため、配列の開始は遅くなります。ですから、アレイ上のカウントは(マシン上で)10倍遅くなります。これは、インタフェースが明示的に実装されている理由の1つになります。 2つのパブリックプロパティ、.Countと.Lengthを持つオブジェクトがあるとします。どちらもまったく同じことですが、.Countは10倍遅くなります。
もちろん、これは実際には違いがあります。なぜなら、あなたの配列を数える必要があり、パフォーマンスヒットを感じるために何百万もの時間を数えてしまうからです。
コード:
static void TimeAction(string description, int times, Action func) {
var watch = new Stopwatch();
watch.Start();
for (int i = 0; i < times; i++) {
func();
}
watch.Stop();
Console.Write(description);
Console.WriteLine(" Time Elapsed {0} ms", watch.ElapsedMilliseconds);
}
static void Main(string[] args) {
var array = Enumerable.Range(0, 10000000).ToArray();
var list = Enumerable.Range(0, 10000000).ToArray().ToList();
// jit
TimeAction("Ignore and jit", 1 ,() =>
{
var junk = array.Length;
var junk2 = list.Count;
array.Count();
list.Count();
});
TimeAction("Array Length", 1000000,() => {
var tmp1 = array.Length;
});
TimeAction("Array Count()", 1000000,() =>
{
var tmp2 = array.Count();
});
TimeAction("Array Length through cast", 1000000,() =>
{
var tmp3 = (array as ICollection<int>).Count;
});
TimeAction("List Count", 1000000,() =>
{
var tmp1 = list.Count;
});
TimeAction("List Count()", 1000000,() =>
{
var tmp2 = list.Count();
});
Console.ReadKey();
}
結果:
Array Length Time Elapsed 3 ms Array Count() Time Elapsed 264 ms Array Length through cast Time Elapsed 16 ms List Count Time Elapsed 3 ms List Count() Time Elapsed 18 ms
いくつかの追加情報 - LINQカウント - 巨大ことができ、それを使用していないとの違い - これは "オーバーである必要はありません。大規模なコレクションも。私はlinqから約6500個のアイテムを持つオブジェクトに結びついたコレクションを持っています(大きなものですが、巨大ではありません)。私の場合のCount()は数秒かかる。リスト(または配列)に変換すると、その数は事実上即時になります。この数を内側のループに入れることは、その影響が大きくなる可能性があることを意味します。 Countはすべてを列挙します。配列とリストは両方ともその長さを「自己認識」しており、列挙する必要はありません。このcount()を参照するすべてのデバッグ文(log4net for ex)は、すべてをかなり遅くします。あなた自身が好意を持ってこれを参照する必要がある場合は、カウントサイズを保存し、それをリストに変換してからパフォーマンスヒットなしに参照することができない限り、LINQコレクションで一度呼び出すだけです。
ここで私が上で話していたことの簡単なテストです。 Count()を呼び出すたびに、コレクションのサイズが変化するので、予想される 'count'演算以上の評価が行われます。 )注意してください:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace LinqTest
{
class TestClass
{
public TestClass()
{
CreateDate = DateTime.Now;
}
public DateTime CreateDate;
}
class Program
{
static void Main(string[] args)
{
//Populate the test class
List list = new List(1000);
for (int i=0; i<1000; i++)
{
System.Threading.Thread.Sleep(20);
list.Add(new TestClass());
if(i%100==0)
{
Console.WriteLine(i.ToString() + " items added");
}
}
//now query for items
var newList = list.Where(o=> o.CreateDate.AddSeconds(5)> DateTime.Now);
while (newList.Count() > 0)
{
//Note - are actual count keeps decreasing.. showing our 'execute' is running every time we call count.
Console.WriteLine(newList.Count());
System.Threading.Thread.Sleep(500);
}
}
}
}
list.WithがCount()でショートカットを取得しないようにIEnumerableを返します...もしあなたがそれを実現したら、かなり良いperfを表示します(例えば: 'list.Where(o => o.CreateDate.AddSeconds(5)> DateTime .Now).ToList() ') –
- 1. C#.NETでは、array.Lengthとlist.Countの理由は何ですか?
- 2. unordered_map:find()またはcount()のどちらが高速ですか?
- 3. "startsWith"は "indexOf"より高速ですか?
- 4. djangoでは、とにかくaggregate(Count())が.count()よりも速く、あるいは良いですか?
- 5. ローカルメンバーがより高速またはインスタンスメンバー
- 6. OpenCLカーネルは、より高速のGPUでより遅く実行する
- 7. なぜarray.lengthはそのような高い数値を返しますか?
- 8. LINQ Count()until、これはより効率的ですか?
- 9. StretchDIBitsが遅いですが、より速いAPIはありますか?
- 10. は、より速くまたは遅くconcatです
- 11. なぜRuby配列[array.length、count]が[]を返すのですか?
- 12. TemplateControl.ParseControlより高速な代替手段はありますか?
- 13. CUDAプログラムはCPUプログラムより低速ですが、カーネルは高速ですか?
- 14. コンストラクタより高速ですか?
- 15. より速いのは何ですか? System.currentTimeMillis()またはDate()。getTime()?
- 16. スレッドはスレッドのバージョンよりはるかに高速ではありません
- 17. Libgdx GestureDetectorパンメソッドは、デバイスの速度が遅く/高速です
- 18. なぜWebViewはTextViewよりもはるかに高速です
- 19. テンプレートのメタプログラミングは同等のCコードより高速ですか?
- 20. MySQLのビューは通常のクエリより高速ですか?
- 21. データ属性のCSSセレクタはクラスセレクタより高速ですか?
- 22. TCPはイーサネット経由のUDPより高速ですか?
- 23. Cassandraは単一ノードクラスタ上のHBaseより高速ですか?
- 24. MSMQがWCF QueueServiceより高速なのはなぜですか?
- 25. Oracleストアドプロシージャは、Microsoft.NETアプリケーションの行SQLよりも高速ですか?
- 26. キャンバスは通常の画像より高速ですか?
- 27. LINQはストアドプロシージャを呼び出すよりも低速ですか?
- 28. なぜVimでは\%(\)が\(\)より高速ですか?
- 29. {Filter}はLuceneで{Query}より高速ですか?
- 30. getterとsetterはより高速に動作しますか?
最も簡単に知る方法は試してみることです。 StopWatchの適切なメソッドへの呼び出しで両方をラップし、数百万回実行すれば、わかります。 –
真剣に大きなコレクションについて話している場合を除き、速度の顕著な違いはありません。読み込み/保守が容易なものだけを使用してください。 – Hardwareguy