web-dev-qa-db-ja.com

大規模なアプリケーションではSTLを避けるべきですか?

これは奇妙な質問のように聞こえるかもしれませんが、私の部門では、次の状況で問題が発生しています。

ここでは、サーバーアプリケーションに取り組んでいます。サーバーアプリケーションをさまざまな部分(DLLファイル)に分割し、必要に応じて動的にロードし、後でアンロードして、処理できるようにすることも検討しています。パフォーマンスの問題。

しかし:私たちが使用している関数は、STLオブジェクトとして入力および出力パラメーターを渡しています スタックオーバーフローの回答で述べたように 、これは非常に悪い考えです。 (投稿にはいくつかの±ソリューションとハックが含まれていますが、すべてが非常に堅固に見えるわけではありません。)

明らかに、入力/出力パラメーターを標準のC++型に置き換えて、関数内でこれらのパラメーターからSTLオブジェクトを作成できますが、これによりパフォーマンスが低下する可能性があります。

1台のPCで処理できないほど大きくなる可能性のあるアプリケーションの構築を検討している場合、STLをテクノロジとして使用してはならない、と結論しても大丈夫ですか?

この質問の背景:
質問についていくつかの誤解があるようです:問題は次のとおりです:
私のアプリケーションは、その作業を完了するために膨大な量のパフォーマンス(CPU、メモリ)を使用しており、この作業を(プログラムがすでに複数の機能に分割されているため)異なる部分に分割したいのですが、私のアプリケーションからいくつかのDLLを作成し、それらのDLLのエクスポートテーブルにいくつかの関数を配置することは困難です。これにより、次の状況が発生します。

+-----------+-----------+----
| Machine1  | Machine2  | ...
| App_Inst1 | App_Inst2 | ...
|           |           |    
| DLL1.1    | DLL2.1    | ...
| DLL1.2    | DLL2.2    | ...
| DLL1.x    | DLL2.x    | ...
+-----------+-----------+----

App_Inst1はMachine1にインストールされたアプリケーションのインスタンスであり、App_Inst2はMachine2にインストールされた同じアプリケーションのインスタンスです。
DLL1.xはMachine1にインストールされたDLLであり、DLL2.xはMachine2にインストールされたDLLです。
DLLx.1はエクスポートされたfunction1をカバーします。
DLLx.2はエクスポートされたfunction2をカバーします。

次にMachine1でfunction1とfunction2を実行します。これによりMachine1が過負荷になることがわかっているので、そのアプリケーションインスタンスにfunction2を実行するように求めるメッセージをApp_Inst2に送信します。

Function1とfunction2の入出力パラメーターはSTL(C++標準タイプライブラリ)オブジェクトであり、App_Inst1、App_Inst2、DLLx.yの更新を定期的に行うことを期待する場合があります(ただし、すべてではありませんが、Machine1をアップグレードする場合がありますが、 Machine2ではなく、またはアプリケーションのみをアップグレードし、DLLはアップグレードしない、またはその逆など)。明らかに、インターフェース(入力/出力パラメーター)が変更された場合、お客様は完全なアップグレードを行う必要があります。

ただし、参照されているStackOverflow URLで言及されているように、App_Inst1またはDLLの1つを単純に再コンパイルすると、システム全体がバラバラになる可能性があるため、この投稿の元のタイトルは、STL(C++標準テンプレートの使用)を推奨していませんライブラリ)。大規模アプリケーション用。

これにより、いくつかの質問/疑問が解消されたことを願っています。

25
Dominique

これは、石のように冷たい古典的なX-Y問題です。

あなたのreal問題はパフォーマンスの問題です。ただし、あなたの質問は、パフォーマンスの問題が実際にどこから発生しているかについて、プロファイリングやその他の評価を行っていないことを明らかにしています。代わりに、コードをDLLに分割することで問題を魔法のように解決できることを願っています(実際にはそうではありません)が、今ではその非解決策の1つの側面について心配しています。

代わりに、実際の問題を解決する必要があります。複数の実行可能ファイルがある場合は、どれがスローダウンの原因となっているかを確認します。その間、実際にプログラムがすべての処理時間を費やしていることを確認してください。構成が不適切なイーサネットドライバーなどではありません。その後、コード内のさまざまなタスクのプロファイリングを開始します。高精度タイマーはあなたの友達です。古典的な解決策は、コードのチャンクの平均および最悪の場合の処理​​時間を監視することです。

データを入手したら、問題の対処方法を見つけ出し、最適化する場所を見つけることができます。

111
Graham

複数の物理マシン間でソフトウェアを分割する必要がある場合、マシン間で実際に同じ正確なバイナリを送信できるのは一部の場合に限られるため、マシン間でデータを渡すときに何らかの形式のシリアル化が必要です。ほとんどのシリアライゼーションメソッドはSTLタイプの処理に問題がないので、そのような場合は心配する必要はありません。

アプリケーションを共有ライブラリ(DLL)に分割する必要がある場合(パフォーマンス上の理由でそれを行う前に、実際にパフォーマンスの問題を解決することを確認する必要があります)STLオブジェクトを渡すことは問題になる場合がありますが、そうする必要はありません。提供したリンクで既に説明したように、同じコンパイラーと同じコンパイラー設定を使用している場合は、STLオブジェクトを渡すことができます。ユーザーがDLLを提供すると、これを簡単に期待できない場合があります。すべてのDLLを提供してすべてを一緒にコンパイルする場合は、それを当てにして、DLLの境界を越えてSTLオブジェクトを使用することが非常に可能になります。それでも、オブジェクトの所有権を渡す場合に複数の異なるヒープを取得しないようにコンパイラー設定。ただし、これはSTL固有の問題ではありません。

38

ここでは、サーバーアプリケーションを処理できるように、必要に応じて動的にロードし、後でアンロードして、さまざまな部分(DLL)に分割することを検討している段階でも、ますます大きくなるサーバーアプリケーションに取り組んでいます。パフォーマンスの問題

RAMは安価であるため、非アクティブなコードは安価です。コードのロードとアンロード(特にアンロード)は脆弱なプロセスであり、最新のデスクトップ/サーバーハードウェアでのプログラムのパフォーマンスに大きな影響を与える可能性はほとんどありません。

キャッシュはより高価ですが、影響を受けるのは最近アクティブなコードのみであり、未使用のメモリにあるコードには影響しません。

一般に、プログラムは、コードサイズではなく、データサイズまたはCPU時間のために、コンピュータのサイズを超えます。コードのサイズが大きくなりすぎて大きな問題が発生している場合は、そもそもなぜそれが起こっているのかを調べたいと思います。

しかし:私たちが使用している関数は、入力パラメーターと出力パラメーターをSTLオブジェクトとして渡しています。このStackOverflow URLで述べたように、これは非常に悪い考えです。

DLLと実行可能ファイルがすべて同じコンパイラでビルドされ、同じC++ランタイムライブラリに対して動的にリンクされている限り、問題ありません。したがって、アプリケーションとそれに関連するdllが1つのユニットとして構築およびデプロイされている場合は、問題にはなりません。

それが問題になる可能性があるのは、ライブラリが別の人によって構築されている場合、または個別に更新できる場合です。

1台のPCで処理できないほど大きくなる可能性のあるアプリケーションの構築を検討している場合、テクノロジーとしてSTLを使用してはならない、と結論しても大丈夫ですか?

あんまり。

アプリケーションを複数のマシンに分散し始めると、それらのマシン間でデータを渡す方法について、さまざまな考慮事項があります。 STLタイプまたはより基本的なタイプが使用されているかどうかの詳細は、ノイズで失われる可能性があります。

20
Peter Green

いいえ、その結論が続くとは思いません。プログラムが複数のマシンに分散している場合でも、STLを内部で使用することにより、モジュール間/プロセス間通信で使用するように強制される理由はありません。

実際、外部インターフェイスの設計は最初から内部実装から分離する必要があると私は主張します。前者は内部で使用されているものよりも堅固で変更が難しいためです。

13
Bwmat

あなたはその質問の要点を逃しています。

DLLには基本的に2つのタイプがあります。あなた自身のものと他の誰かのものです。 「STLの問題」は、あなたと彼らが同じコンパイラを使用していない可能性があることです。明らかに、それはあなた自身のDLLの問題ではありません。

7
MSalters

同じコンパイラとビルドオプションを使用して、同じソースツリーから同時にDLLをビルドすると、問題なく動作します。

ただし、アプリケーションを複数の部分に分割する「Windows風味」の方法は、COMコンポーネントです。これらは小さい(個別のコントロールまたはコーデック)または大きい(IEは、mshtml.dllのCOMコントロールとして使用できます)のいずれかです。

必要なときに動的にロードし、後でアンロードする

サーバーアプリケーションの場合、これはおそらくひどい効率になるでしょう。長期間にわたって複数のフェーズを通過するアプリケーションがあり、何かが再び必要とされなくなる時期がわかる場合にのみ、それは本当に実行可能です。オーバーレイメカニズムを使用したDOSゲームを思い出します。

さらに、仮想メモリシステムが適切に機能している場合は、未使用のコードページをページングして処理します。

1台のPCで処理できないほど大きくなる可能性がある

より大きなPCを購入します。

忘れないでください 適切な最適化により、ラップトップはHadoopクラスタよりも優れたパフォーマンスを発揮します。

本当に複数のシステムが必要な場合は、それらの間の境界について非常に注意深く検討する必要があります。それがシリアライゼーションのコストがかかる場所だからです。ここから、MPIなどのフレームワークを検討する必要があります。

5
pjc50

ここでは、サーバーアプリケーションに取り組んでいます。サーバーアプリケーションをさまざまな部分(DLLファイル)に分割し、必要に応じて動的にロードし、後でアンロードして、処理できるようにすることも検討しています。パフォーマンスの問題。

最初の部分は理にかなっています(パフォーマンス上の理由から、アプリケーションを別のマシンに分割します)。

2番目の部分(ライブラリーのロードとアンロード)は意味のあることではありません。これは追加の作業であり、(実際には)改善されないためです。

あなたが説明している問題は、専用の計算機でよりよく解決されますが、これらは同じ(メイン)アプリケーションでは動作しないはずです。

従来のソリューションは次のようになります。

[user] [front-end] [machine1] [common resources]
                   [machine2]
                   [machine3]

フロントエンドマシンと計算マシンの間に、ロードバランサーやパフォーマンスモニタリングなどの追加機能がある場合があります。専用マシンでの特殊な処理のキーイングは、キャッシュとスループットの最適化に適しています。

これは、DLLの追加のロード/アンロードや、STLとの関係を意味するものではありません。

つまり、必要に応じて内部でSTLを使用し、要素間でデータをシリアル化します(grpcとプロトコルバッファー、およびそれらが解決する問題の種類を参照してください)。

これは、あなたが提供した限られた情報で、これは古典的なx-y問題のように見えます(@Grahamが言ったように)。

0
utnapistim