5

私はJavaプログラミングから来て、C#プログラミングに切り替えて、LINQの非常に強力なものを発見しました。

foreach最近の実装では、ループを回避したり、リスト内の要素を検索したり、同様のタスクを実行したりするために、コードで頻繁に使用していることに気付きました(特にLINQ to Objects) 。

今、Linq to Objectsを大量に使用すると、パフォーマンスが低下するのではないかと思います...

4

4 に答える 4

26

LinqはネイティブC#ループよりも低速です。
C#はC++よりも低速です。
C++はアセンブリよりも低速です。
組み立ては、独自のカスタムマイクロプロセッサを設計するよりも時間がかかります。

したがって、Linqを使用するのではなく、常に独自のカスタムマイクロプロセッサを設計する必要があります。

パフォーマンスに影響はありますか?おそらく、しかし実際にそれを測定するまで、あなたはどれくらいかわかりません。それは重要ではないほど十分に小さい可能性があり、Linqが最適化によって利益を得るアプリケーションの部分に取り組むことを回避するために費やしたであろう時間を費やすことができます。

要点は、最も生産性の高いライブラリとフレームワークを使用してアプリを構築し、そこから最適化することです。アプリの最も遅い部分がLinqコードではないことに気付くかもしれません。そのため、独自のループをロールするよりも遅い可能性があるという理由だけでそれを禁止すると、間違ったものを最適化することになります。

于 2012-10-26T13:13:46.490 に答える
11

質問に客観的に答えるために、LINQはデリゲートとイテレーターを多用します。これには、インスタンス化(デリゲートとイテレーター)とメソッド呼び出し(デリゲート呼び出しとイテレーター)のオーバーヘッドがありますMoveNext()。これで、foreach(上のList<T>)にはイテレータのオーバーヘッドがありますが、デリゲートのオーバーヘッドはありません。したがって、ここではLINQが。よりも遅くなることが予想されますforeach

同様に、[i]インデクサーを使用してリストを反復処理することも、イテレーターのオーバーヘッドがないため、さらに高速になると予想されます。さらに高速なのはList<T>、配列ではなく配列を使用することです。しかし、それでも配列境界チェックのオーバーヘッドがあり(配列境界のIndexOutOfRangeException外に出ようとするとをスローするビット)、ポインターを介した生のメモリアクセスを使用するか、リスト全体を反復することで回避できますfor(var i = 0; i < array.Length; i++) { Console.WriteLine(array[i]); }(コンパイラはこのループが境界を超えないことを証明できるため、境界チェックを行います)。

これらは、さまざまな反復方法によってもたらされるさまざまな程度のオーバーヘッドです。それらのオーバーヘッドは重要ですか?10,000 x 10,000の行列乗算を実行している場合は、そうです。そうでなければ、おそらくあなたがそれを測定していない限りそうではありません(これは疲れた古い答えですが、それほど有効ではありません)。

ただし、これらの事実とは別に、それらをどのように使用するかも重要です。1980年以降に多数の顧客から生まれた顧客のリストが必要であり、さらに処理を行うとします。LINQがないと、元の顧客リストにかなり強制されforeach、1980年以降に生まれた顧客を入れる中間リストを作成することになります。LINQを使用すると、オーバーヘッドを大幅に節約する中間リストは必要ありません(リストの作成、呼び出しAddその上で、成長するにつれて数倍のサイズ変更を行う可能性が高くなります)、より高速になる可能性があります。また、1980年以降に生まれた顧客は、中間リストがメモリを占有することなく1つずつ「ストリーミング」されるため、メモリ効率が確実に向上します。LINQを使用すると、無限に長いシーケンスを処理できる可能性があります。

LINQを使用するもう1つのパフォーマンス上の理由AsParallel()は、クエリの最後の呼び出しで特定の操作の並列化が簡単になることです。

したがって、LINQの使用にパフォーマンス上の不利な点がある場合は、質問に答えてください。

場合によります。

于 2012-10-26T21:21:45.610 に答える
0

大まかに言えば、LINQにはパフォーマンス上の利点はありませんが、一部の実装ではメリットがある可能性があります。パフォーマンスの高いコードが必要な場合でも、各LINQクエリのアルゴリズムの時間計算量を広く認識している必要があります。

たとえば、私が見た一般的なシナリオは、特定の値のリストに対してWHERE句を実行することです。これにより、リスト内のアイテムがスキャンされ、O(n)の複雑さが発生します。Dictionary<K,V>もちろん、このような操作は、ルックアップを実行するためのハッシュテーブル(たとえば)を維持する場合、O(1)の複雑さで実現できます。

于 2012-10-26T13:14:47.783 に答える
0

制御を失い、基盤となるコードを認識していない実装に依存する必要がある抽象化では、パフォーマンスが低下する傾向があります(LINQは汎用である必要があり、犠牲を払って1つのタイプのオブジェクトに対して完全に最適化できないため)別の)。ただし、状況によって異なります。たとえば、アプリケーションが1日に何百万回もヒットし、絶対的なパフォーマンスが必要な場合、データベースクエリのエンティティにLINQを使用することはおそらく良い考えではありません。その場合、LINQでは許可されないSQLクエリのパフォーマンスの最適化を行うことができます。行う。ただし、アプリケーションがユーザー数が比較的少ないエンタープライズアプリケーションの一部として使用されている場合は、LINQを多用しても問題ない可能性があります。だから私の答えはイエスですそれは遅くなるでしょう、

于 2012-10-26T13:02:14.913 に答える