タグ付けされた質問 「performance」

アプリケーションのパフォーマンスの向上に関する質問です。これは、ソフトウェアアーキテクチャの選択からアルゴリズムの選択までさまざまです。

3
ループ内で変数を定義するのは良いですか?[閉まっている]
閉じた。この質問には、詳細または明確さが必要です。現在、回答を受け付けていません。 この質問を改善したいですか?詳細を追加し、この投稿を編集して問題を明確にします。 4年前に閉鎖されました。 私のインストラクターはかつて、ループ内で変数を定義するべきではないと教えてくれましたが、正直なところまだ理由がわかりません。 その欠点は何ですか? 体はそれを私に説明できますか?

1
Collection.stream()。filter()。forEach()は、各ループの標準と比較して非効率ですか?
IntelliJ IDEAは、次のfor-eachループをJava 8の "forEach"呼び出しに置き換えるために、今私に勧めました: for (Object o : objects) { if (o instanceof SomeObject) { doSomething(); } } 推奨される呼び出しは次のようになります。 objects.stream().filter(o -> o instanceof SomeObject).forEach(o -> doSomething()); Streamの基本的な機能がどのように機能するかを誤解していない限り、streamの使用は標準のfor-eachループのO(n)操作ではなくO(2n)操作であるように思われます。


4
SIMDプログラミングコードベースのメンテナンスコスト
質問: ソフトウェア業界のコンセンサスは、クリーンでシンプルなコードが、コードベースとそれを所有する組織の長期的な実行可能性の基本であるということです。これらのプロパティにより、メンテナンスコストが削減され、コードベースが継続される可能性が高まります。 ただし、SIMDコードは一般的なアプリケーションコードとは異なります。SIMDコードに特に適用されるクリーンでシンプルなコードに関して、同様のコンセンサスがあるかどうかを知りたいと思います。 私の質問の背景。 さまざまな画像処理および分析タスクのために、たくさんのSIMD(単一命令、複数データ)コードを作成します。最近、これらの関数のいくつかを、あるアーキテクチャ(SSE2)から別のアーキテクチャ(ARM NEON)に移植しなければなりませんでした。 このコードはシュリンクラップされたソフトウェア用に記述されているため、MATLABなどの無制限の再配布権がなければ、独自の言語に依存することはできません。 典型的なコード構造の例: 使用のOpenCVのマトリックスタイプ(Mat)すべてのメモリのため、緩衝液および寿命管理。 入力引数のサイズ(次元)を確認した後、ピクセルの各行の開始アドレスへのポインターが取得されます。 ピクセルカウント、および各入力マトリックスからのピクセルの各行の開始アドレスは、いくつかの低レベルC ++関数に渡されます。 これらの低レベルC ++関数は、SIMD組み込み関数(Intel ArchitectureおよびARM NEON用)を使用して、生のポインターアドレスからの読み込みと保存を行います。 これらの低レベルC ++関数の特徴: 排他的に1次元(メモリ内で連続) メモリ割り当てを処理しません。(一時を含むすべての割り当ては、OpenCV機能を使用する外部コードによって処理されます。) シンボルの名前の長さの範囲(組み込み関数、変数名など)は約10〜20文字で、これは非常に過剰です。(テクノバブルのように読みます。) コンパイラは「単一割り当て」コーディングスタイルで記述されていないコードを正しく解析するのに非常にバグがあるため、SIMD変数の再利用は推奨されません。(私はいくつかのコンパイラのバグレポートを提出しました。) SIMDプログラミングのどの側面が議論を一般的な場合と異なるものにしますか?または、SIMDが異なるのはなぜですか? 初期開発コストの観点から 優れたパフォーマンスを備えたC ++ SIMDコードの初期開発コストは、カジュアルに記述された C ++コードと比較して、約10倍から100倍(マージンは大きい)であることはよく知られています。 パフォーマンスと読み取り可能/クリーナーコードの選択の回答で述べたように?、ほとんどのコード(カジュアルに記述されたコードとSIMDコードを含む)は、最初はクリーンでも高速でもありません。 (スカラーコードとSIMDコードの両方での)コードパフォーマンスの進化的な改善は推奨されません(ソフトウェアの一種と見なされるため)。コストと利点は追跡されません。 傾向の観点から (例えば、パレート原理、別名80-20ルール) 画像処理がソフトウェアシステムの20%(コードサイズと機能の両方)のみで構成されている場合でも、画像処理は(CPU時間の割合として見た場合)比較的遅く、80%以上の時間がかかります。 これは、データサイズの影響によるものです。典型的な画像サイズはメガバイト単位で測定されますが、非画像データの典型的なサイズはキロバイト単位で測定されます。 画像処理コード内で、SIMDプログラマーは、C ++コード内のループ構造を識別することにより、ホットスポットを含む20%コードを自動的に認識するように訓練されます。したがって、SIMDプログラマーの観点からは、「重要なコード」の100%がパフォーマンスのボトルネックです。 多くの場合、画像処理システムには複数のホットスポットが存在し、同等の割合の時間を消費します。たとえば、5つのホットスポットがそれぞれ合計時間(20%、18%、16%、14%、12%)を占める場合があります。高いパフォーマンスを実現するには、すべてのホットスポットをSIMDで書き換える必要があります。 これは、バルーンをポップするルールとして要約されています。バルーンを2回ポップすることはできません。 バルーンがいくつかあると仮定します。たとえば、そのうち5つです。それらを間引く唯一の方法は、それらを1つずつポップすることです。 最初のバルーンがポップされると、残りの4つのバルーンの合計実行時間の割合が高くなります。 さらに利益を上げるには、別のバルーンをポップする必要があります。(これは、最適化の80-20ルールに反します:ぶら下がりが最も少ない果物の20%が選ばれた後、良好な経済的結果を達成できます。) 読みやすさとメンテナンスの面で SIMDコードは、明らかに読みにくいです。 これは、すべてのソフトウェアエンジニアリングのベストプラクティス(ネーミング、カプセル化、const-correctness(および副作用の明確化)、関数の分解など)に従っても当てはまります。 これは、経験のあるSIMDプログラマーにも当てはまります。 最適なSIMDコードは、同等のC ++プロトタイプコードと比較して、非常にゆがんでいます(注意を参照)。 SIMDコードをゆがめる方法は数多くありますが、10回の試行のうち1回だけで許容可能な高速の結果が得られます。 (つまり、高い開発コストを正当化するために、4倍から10倍のパフォーマンスゲインを調整します。実際には、さらに高いゲインが観察されています。) …

5
試しに最終的に高価です
関数を終了する前にリソースのクリーンアップを行う必要があるコードの場合、これらの2つの方法の間に大きなパフォーマンスの違いがあります。 すべてのreturnステートメントの前にリソースをクリーニングする void func() { login(); bool ret = dosomething(); if(ret == false) { logout(); return; } ret = dosomethingelse(); if(ret == false) { logout(); return; } dootherstuff(); logout(); } finallyブロックでのリソースのクリーニング void func() { login(); try { bool ret = dosomething(); if(ret == false) return; ret = dosomethingelse(); if(ret == …


4
単体テストのタイムアウトを使用してメソッドのパフォーマンスを測定することをお勧めしますか?
特定のアクションの最大実行時間を指定する非機能要件があるプロジェクトでは、QAは、要件で指定されているハードウェアと負荷の両方の正確な負荷の下で、正確なハードウェアを使用して専用マシンでこのアクションのパフォーマンスを確認する必要があります。 一方、ソースコードに誤った変更を加えると、パフォーマンスに深刻な影響を与える可能性があります。早くこのマイナスの影響に着目、前のソースコードは、ソースコントロールに到達し、QA部門によって検証され、問題の報告QA部門によって失われた時間の点で有益であり、開発者が後でそれをいくつかのコミットを固定できます。 これを行うには、良いアイデアですか? ユニットテストを使用して、同じアクション²をn回実行するのにかかった時間を把握するには、 C#の属性を介してテストごとのタイムアウトを使用するには[TestMethod, Timeout(200)]? このアプローチにはいくつかの問題が予想されます。 概念的には、ユニットテストは実際にはそのためのものではありません。コードのごく一部をテストするだけであり、機能要件のチェック、統合テスト、パフォーマンステストのいずれでもありません。 Visual Studioの単体テストタイムアウトは、初期化とクリーンアップがこれらのテストに存在しないか、結果に影響を与えるには短すぎることを考慮して、実際に測定されると予想されるものを測定しますか? この方法でパフォーマンスを測定するのはいです。ハードウェア、負荷などに関係なく、任意のマシン¹でベンチマークを実行することは、あるデータベース製品が別のデータベース製品よりも常に高速であることを示すベンチマークを実行するようなものです。一方で、これらの単体テストが決定的な結果になることや、QA部門で使用されるものになることは期待していません。これらの単体テストは、期待されるパフォーマンスについての一般的なアイデアを提供するためだけに使用され、基本的に、開発者に最後の変更が何かを壊し、パフォーマンスに重大な影響を与えることを開発者に警告します テスト駆動開発(TDD)は、これらのテストでは不可能です。コードの実装を開始する前に、そもそもどのように失敗しますか? パフォーマンステストが多すぎると、テストの実行に必要な時間に影響するため、このアプローチは短いアクションのみに制限されます。 これらの問題を考慮すると、QA部門による実際のパフォーマンスメトリックと組み合わせた場合、このような単体テストを使用することは依然として興味深いと思います。 私が間違っている?これに単体テストを使用することを完全に受け入れられないようにする他の問題はありますか? 私が間違っている場合、ソースコードがソース管理に到達してQA部門によって検証される前に、ソースコードの変更がパフォーマンスに深刻な影響を与えたことを開発者に警告する正しい方法は何ですか? ¹実際、ユニットテストは、同等のハードウェアパフォーマンスを備えた開発者のPCでのみ実行されることが期待されています。 ²アクションとは、実行に数ミリ秒かかるかなり短いコードのことです。

10
オブジェクト指向は本当にアルゴリズムのパフォーマンスに影響しますか?
オブジェクト指向は、多くのアルゴリズムを実装する上で非常に役立ちました。ただし、オブジェクト指向言語は「簡単な」アプローチをガイドすることがあり、このアプローチが常に良いものかどうかは疑問です。 オブジェクト指向は、アルゴリズムを高速かつ簡単にコーディングするのに非常に役立ちます。しかし、このOOPは、パフォーマンスに基づいたソフトウェアにとって不利なものになる可能性があります。つまり、プログラムの実行速度です。 たとえば、グラフノードをデータ構造に格納することは、最初は「簡単」に思えますが、Nodeオブジェクトに多くの属性とメソッドが含まれている場合、アルゴリズムが遅くなる可能性はありますか? 言い換えれば、多くの異なるオブジェクト間の多くの参照、または多くのクラスの多くのメソッドを使用すると、「重い」実装になりますか?

5
アルゴリズムの複雑さをテストする必要がありますか?もしそうなら、どのように?
ソートされたリスト/配列の検索のような単純なものを実装しているとしましょう。関数(c#内)は次のようになります。 static int FindIndex(int[] sortedList, int i); 機能の面でこれを実装してテストすることもできますが、明らかな理由から、通常は線形検索や意図的に愚かなものよりもバイナリ検索を好むでしょう。 だから私の質問は次のとおりです。アルゴリズムの複雑さの観点からパフォーマンスを保証するテストを作成する必要がありますか? 私はこの質問の「あなたがすべき」部分の両側で議論を始めましたが、私はそれらを促すために私の議論なしで人々が言うことを見てみたいです。 「方法」に関しては、非常に興味深いものになります:)比較演算子をパラメーター化して、比較演算子が比較などをカウントするテストを持つことがわかります。しかし、あなたができるからといって... 他の誰かが(おそらく)これを考えましたか?ありがとう。

4
基本的なハードウェアと機能的パラダイムがあまりにも異なるため、一般的に効率的ではないでしょうか?
SOからの質問に触発された:https : //stackoverflow.com/questions/6623391/how-to-gain-control-of-a-5gb-heap-in-haskell FPの多くの長所と短所については長い議論の余地がありますが、現時点では、最新のハードウェアでのFPの主な効率に範囲を絞りたいと思います。 定説: 機能的パラダイムは不変性とステートレス(?)を意味しますが、機能的プログラムを実行するハードウェアはステートフルな有限オートマトンです。「純粋な機能」プログラムを「ステートフルなハードウェア」表現に変換すると、プログラマーはほとんど制御できず、オーバーヘッド(?)が発生し、ハードウェア機能の使用が制限されます(?)。 私は疑問の声明で正しいか間違っていますか? FPは、現代の汎用コンピューターアーキテクチャでの主要なパフォーマンスペナルティを意味する/しないことを証明できますか? 編集: いくつかのコメントに応じて既に述べたように、質問は実装のパフォーマンスと詳細に関するものではありません。これは、プリンシパルオーバーヘッドの有無に関するものであり、ステートフルオートマトンでFPを実行するともたらされる可能性があります。

4
お気に入りのビット単位のテクニックは何ですか?[閉まっている]
現在のところ、この質問はQ&A形式には適していません。回答は事実、参考文献、または専門知識によってサポートされると予想されますが、この質問は議論、議論、世論調査、または広範な議論を求める可能性があります。この質問を改善し、場合によっては再開できると思われる場合は、ヘルプセンターをご覧ください。 7年前に閉鎖されました。 ロックされています。この質問とその回答はロックされています。なぜなら、質問はトピックから外れていますが、歴史的に重要だからです。現在、新しい回答やインタラクションを受け入れていません。 数日前、StackExchangeのメンバーであるAntoは、ビット単位の演算子の有効な使用方法について問い合わせました。私は、整数を2のべき乗で乗算および除算するよりも高速であると述べました。StackExchangeメンバーのDaeminは、右シフトが負の数の問題を引き起こしたと述べて反論しました。 その時点で、符号付き整数でシフト演算子を使用することを考えたことはありませんでした。私は主に低レベルのソフトウェア開発でこの手法を使用しました。したがって、常に符号なし整数を使用しました。Cは、符号なし整数で論理シフトを実行します。論理右シフトを実行する場合、符号ビットには注意が払われません。空白ビットはゼロで埋められます。ただし、Cは符号付き整数を右にシフトするときに算術シフト演算を実行します。空白ビットは符号ビットで埋められます。この違いにより、負の値はゼロに切り捨てられるのではなく、無限に丸められます。これは、符号付き整数除算とは異なる動作です。 数分考えた結果、一次解決策が生まれました。このソリューションは、シフトする前に条件付きで負の値を正の値に変換します。値は、シフト操作が実行された後、条件付きで負の形式に変換されます。 int a = -5; int n = 1; int negative = q < 0; a = negative ? -a : a; a >>= n; a = negative ? -a : a; このソリューションの問題は、通常、条件付き割り当てステートメントが少なくとも1つのジャンプ命令に変換されることであり、ジャンプ命令は、両方の命令パスをデコードしないプロセッサーでは高価になる可能性があります。命令パイプラインを2回再プラ​​イミングしなければならないことは、除算をオーバーシフトすることで得られるパフォーマンスの向上に良い影響を与えます。 上記で述べたように、私は土曜日に条件付き割り当ての問題に対する答えで目が覚めました。算術シフト演算を実行するときに発生する丸めの問題は、2の補数表現を操作する場合にのみ発生します。補数表現では発生しません。この問題を解決するには、シフト操作を実行する前に2の補数値を1の補数値に変換します。次に、1の補数値を2の補数値に変換する必要があります。驚くべきことに、シフト操作を実行する前に負の値を条件付きで変換することなく、この一連の操作を実行できます。 int a = -5; int n = 1; register int sign …

2
共有キャッシュ-無効化のベストプラクティス
キャッシュオブジェクトを無効化/更新するためのより良いアプローチは何か知りたいです。 前提条件 リモートmemcachedサーバーを持つ(複数のアプリケーションのキャッシュとして機能する) すべてのサーバーはAzure(アフィニティリージョン、同じデータセンター)によってホストされます キャッシュオブジェクトのサイズは200バイトから50キロバイトまでの範囲です アプローチ1(できるだけ早くキャッ​​シュに保存) オブジェクトAが作成されます->データベースに保存し、キャッシュに保存します クライアントによって要求されたオブジェクトA->キャッシュの存在をチェック、そうでなければデータベースからフェッチしてキャッシュに保存 オブジェクトAが更新されます->データベースに保存、キャッシュに保存 アプローチ1はより簡単なようです。何かが作成されたら、できるだけ早くキャッ​​シュに入れてください。誰かに関係なくそれが必要になります。 アプローチ2(遅延キャッシュストア) オブジェクトAが作成されます->データベースに保存 クライアントによって要求されたオブジェクトA->キャッシュの存在をチェック、そうでなければデータベースからフェッチしてキャッシュに保存 オブジェクトAが更新されます->データベースに保存、キャッシュのキーを削除 アプローチ2は、より多くのメモリを認識しているようです。このアプローチでは、リクエストされたアイテムのみがキャッシュに保存されます。 質問1:パフォーマンスを考慮して、より良いアプローチは何でしょうか?メモリもCPUもまだカウントされません。 質問2:私の考えは一種の時期尚早な最適化ですか? 質問3:他に考えはありますか?他のアプローチ?

5
SqlConnectionsをDispose()しないことはどれほど悪いですか?
個人的には、usingステートメントにIDisposableを実装するADOオブジェクトを配置しないと、ハイブが発生します。しかし、私の現在の契約では、自社開発のエンタープライズフレームワークの「データアクセスプロバイダー」コードは、1)IDisposableを実装せず、2)使用するあらゆるものに対してDispose()をいつでも呼び出さないことがわかりました。ユーザーは、このフレームワークをデータアクセスに頻繁に使用するWinformsアプリケーションのパフォーマンスの問題について多くの不満を述べています。また、コードにはパフォーマンスに影響を与える可能性のある他の問題がたくさんありますが、他よりも垂れ下がった果物。 だから、「廃棄するのは理由があるのでそれを使う」といったことを言う以外に、これらの人々に、これが本当に、本当に悪いと納得させるように言うことができますか?

7
高頻度イベントを接続制限のあるデータベースに保存する
サーバーに大量のイベントが流入し、平均して1秒あたり約1000イベント(ピークは〜2000)に対処しなければならない状況があります。 問題 私たちのシステムはHerokuでホストされ、比較的高価なHeroku Postgres DBを使用します。これにより、最大500のDB接続が可能になります。接続プーリングを使用して、サーバーからDBに接続します。 DB接続プールが処理できるよりも速くイベントが入ります 私たちが抱えている問題は、イベントが接続プールが処理できるよりも速く来るということです。1つの接続がサーバーからDBへのネットワークラウンドトリップを終了するまでに、n追加のイベントが入るよりも多く、プールに解放されます。 最終的に、イベントは蓄積され、保存されるのを待機します。プールに使用可能な接続がないため、タイムアウトし、システム全体が動作不能になります。 クライアントから遅いペースで問題のある高周波イベントを発信することで緊急事態を解決しましたが、その高周波イベントを処理する必要がある場合にこのシナリオを処理する方法を知りたいです。 制約 他のクライアントがイベントを同時に読み取りたい場合があります 他のクライアントは、DBにまだ保存されていない場合でも、特定のキーを持つすべてのイベントの読み取りを継続的に要求します。 クライアントはGET api/v1/events?clientId=1、クライアント1によって送信されたすべてのイベントを照会して取得できます。それらのイベントがまだDBに保存されていない場合でもです。 これに対処する方法に関する「教室」の例はありますか? 可能な解決策 サーバーのイベントをキューに登録します サーバー上のイベントをキューに入れることができます(キューの最大同時実行数は400であるため、接続プールが不足することはありません)。 次の理由により、これは悪い考えです。 使用可能なサーバーメモリを使い果たします。スタックされたエンキューイベントは、大量のRAMを消費します。 サーバーは24時間ごとに1回再起動します。これはHerokuによって課される厳しい制限です。イベントがエンキューされている間にサーバーを再起動すると、エンキューされたイベントが失われます。 サーバーに状態が導入されるため、スケーラビリティが低下します。マルチサーバー設定があり、クライアントがキューに入れられたイベントと保存されたイベントをすべて読みたい場合、キューに入れられたイベントがどのサーバーに存在するかはわかりません。 別のメッセージキューを使用する メッセージキュー(RabbitMQなど)を使用して、メッセージをポンプで送り、もう一方の端にはDB上のイベントの保存のみを処理する別のサーバーがあると仮定します。 メッセージキューがエンキューされたイベント(まだ保存されていない)のクエリを許可するかどうかわからないので、別のクライアントが別のクライアントのメッセージを読みたい場合、DBから保存されたメッセージとキューから保留中のメッセージを取得できますそれらを連結して、読み取り要求クライアントに返送できるようにします。 複数のデータベースを使用し、それぞれが中央のDBコーディネーターサーバーでメッセージの一部を保存して、それらを管理します しかし、もう1つの解決策は、中央の「DBコーディネーター/ロードバランサー」で複数のデータベースを使用することです。イベントを受信すると、このコーディネーターはメッセージを書き込むデータベースの1つを選択します。これにより、複数のHerokuデータベースを使用できるようになり、接続の制限がデータベースの500倍になります。 読み取りクエリで、このコーディネーターはSELECT各データベースにクエリを発行し、すべての結果をマージして、読み取りを要求したクライアントにそれらを送り返すことができます。 次の理由により、これは悪い考えです。 この考えは...ええと..オーバーエンジニアリングのように聞こえますか?同様に管理するのは悪夢です(バックアップなど)。構築と保守は複雑で、絶対に必要でない限り、KISS違反のように聞こえます。 一貫性を犠牲にします。このアイデアを採用すれば、複数のDBでトランザクションを実行することはできません。

5
C ++よりも高速なJavaヒープ割り当て
私はすでにこの質問をSOに投稿しましたが、大丈夫でした。それは残念ながら閉じられました(再開するには1票しか必要ありません)が、誰かが私がここに投稿することを提案したので、それはより適切なので、以下は文字通り質問のコピーペーストです この答えに関するコメントを読んでいたこの引用を見ました。 オブジェクトのインスタンス化とオブジェクト指向の機能は、最初から設計されているため、非常に高速です(多くの場合、C ++よりも高速です)。コレクションは高速です。ほとんどの最適化されたCコードであっても、標準Javaはこの領域で標準C / C ++に勝ります。 あるユーザー(私が追加する可能性のある非常に高い担当者)は、この主張を大胆に擁護し、 Javaでのヒープ割り当てはC ++よりも優れています Javaでコレクションを守るこのステートメントを追加しました また、主にメモリサブシステムが異なるため、JavaコレクションはC ++コレクションに比べて高速です。 だから私の質問はこれのどれでも本当に真実でありえ、もしそうなら、なぜJavaのヒープ割り当てがそんなに速くなるのかということです。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.