5

(これは一般的な架空の質問であり、.NETは豚であり、理由で物乞いをしていると私は嘆きました。実際には、私の特定のアプリについての質問ではありませんでした。)

現在、C#で古いC++コードを書き直しています。すべてのレガシーアプリケーションを移植しています。最大3%のCPUを使用するC++アプリケーションがあります。ほとんどの場合、それらは何も使用しません。次に、コードを取得し、コピーして貼り付けてから、C#構文と.NETライブラリ、およびBAMに再フォーマットします。50%のCPU。これの理由は何ですか?最初はJITだと思っていたのですが、各コードパスを練習して、全部JITした後も、同じ問題です。

また、メモリが大幅に増加していることに気づきました。フルロードで9MBを使用していたアプリは、10 MBで開始し、50MBで実行するようになりました。ハードウェアは安いと思いますが、その原因を知りたいです。それは警報の原因ですか、それとも.NETはそれだけの豚ですか?

スキート射撃への1つの回答を更新

私はC#に精通しています。私は物事をLinqなどに変更します。私は通常、コードを取得して行数を減らします。.NETでC++の人が間違っていることの例をもう少し挙げていただけますか?

アップデート2

これは一般的な質問でしたが、問題のある特定のアプリは次のとおりです。

パラドックスデータベースからデータを取得するためにODBCドライバーを使用するスレッドがあります。次に、Linqを使用してこれをSQLデータベースに変換し、投稿します。ANTSプロファイラーを実行しましたが、データセットの入力に最も時間がかかるようです。続いてLinqの投稿。私の領域のいくつかがリフレクションの使用法であることは知っていますが、これなしで必要なことを行う方法がわかりません。文字列を文字列ビルダーに変更する予定です。これら2つの間に違いはありますか?

(int)datarow["Index"]

ConvertTo.Int32(datarow["Index"])

すべての文字列の連結をフォーマット文字列に変更しました。それは頭上で減少しませんでした。データリーダーとデータアダプターおよびデータセットの違いを知っている人はいますか?

4

5 に答える 5

17

C#と.NETにどの程度精通していますか?C ++イディオムを保持しているレガシーコードを移植しているだけの場合、それが独り占めであることにまったく驚いていません。あるプラットフォームから別のプラットフォームにアプリケーションを逐語的に移植することは、ほとんど決して良い考えではありません。(もちろん、間違いなくそうしているとは言っていません。)また、C ++のエキスパートであるが、.NETの初心者の開発者である場合は、プラットフォームの初心者であるかのようにコードが実行されることを期待する必要があります。

アプリについて詳しく知らなければ、パフォーマンスが何をしているのかを実際に知ることはできません。ただし、文字列の連結が原因であると聞いても驚くことはありません。ボックスにはいくつのプロセッサがありますか?2の場合、アプリは基本的に1つのスレッドで可能なすべてのことを実行しています...

.NETは通常、C ++アプリよりもメモリの点で重くなりますが、ほとんどのタスクの速度の点では少なくとも同等である必要があります。9MBではなく50MBを使用することは、私が予想していたよりも多いように思えますが、すぐにはそれほど心配することはありません。

優れたプロファイラーを使用して、メモリとCPUの両方のパフォーマンスを調査する必要があります。JetBrains dotTrace Profilerをお勧めしますが、他にもたくさんあります。

于 2009-09-15T19:31:03.090 に答える
6

AFAIKとの間にはわずかな違いが(int)datarow["Index"]ありConvertTo.Int32(datarow["Index"])ます。ただし、ストリームモードのデータリーダーを使用する場合は、大きな違いがあります。

int orderIndex = <order of Index column in projection list>;
using (OdbcDataReader rdr = cmd.ExecuteReader(CommandBehavior.SequentialAccess))
{
  int Index = rdr.GetInt32(orderIndex);
}

コマンドのSeqentialAccess動作は、ランダムアクセスに必要な余分なキャッシュを排除するため、SQLの結果を処理するための最速の方法です。

2つ目の注意点は、データセットを使用しているようだということです。データセットは使いやすいですが、誰もが「高速」と呼べるものとはかけ離れています。データセットを使用すると、基本的にメモリ内ストレージエンジンを実行します( Rushmoreに基づいていると思います)。すべてのCPUサイクルとRAMのすべてのビットからすべての1を絞り出したい場合は、よりスリムなコンポーネント(たとえば、DatasetsとDataTablesの代わりに構造体の生の配列)を使用する必要があります。

リンゴとリンゴを比較すると、CLRはネイティブコードに対抗することができます。ILコードは、展開時にNGENを使用してネイティブ化できます。境界チェックなどの一般的なCLRオーバーヘッドを回避できます。GCプリエンプションの「一時停止」は、割り当てに不注意な場合にのみ発生します(GCがあるからといって、左右に割り当てる必要があるとは限りません)。また、CLRは、アクセスパターンに合わせてメモリ内のオブジェクトを再配置し、TLBとL2の局所性を向上させることができるため、メモリレイアウトに関しては実際にいくつかのエースを持っています。

ところで、「C ++はC#の周りを円を描くことができる」という議論は新しいものだと思うなら、CがC ++の周りを円を描くことができたときのことを覚えています(「仮想呼び出しは非常に遅い」と彼らは言っていました)。 Cの周りを一周していました。

于 2009-09-15T20:24:25.027 に答える
1

CPU使用率がいくらか増加するはずです。3%から50%は多すぎるように聞こえますが、これはどのようなコードですか?

メモリフットプリントは、避けられないコストです。.NETアプリの場合は30〜50MBであれば正常です。通常、.NETアプリケーションの実際のメモリ使用量は非常に少ないですが、回避できないかなりの実行時オーバーヘッドがあり(これは1回限りのコストですが、そこにあります)、大量のアセンブリを参照すると非常に目立ちます。 。

于 2009-09-15T19:32:27.160 に答える
0

私はいくつかの推測を考えることができます:

1)メモリ-C++には管理メモリがありません。したがって、メモリを段階的に解放し、(適切にプログラムされている場合は)最適な時間に解放します。

マネージドメモリを使用すると、プログラムは基本的に、ガベージコレクションを実行することを選択するまでメモリを「リーク」します。時間は、おそらくプロセスに割り当てられたメモリの量に依存します。デフォルトの動作を変更する方法はおそらくありますが、メモリサイズが小さいということは、ガベージコレクションの収集がより早く、より頻繁に行われることを意味し、処理時間に影響します。十分なメモリが割り当てられている場合は、gcを呼び出す必要がない場合があります。

2)プログラムは同時に実行されますか、それとも実行されませんか?5倍のプロセッサパワーを使用しているが、1/5の時間で完了する場合、使用されるCPUは基本的に同等です。

3)はい、.NETはおそらく豚です

于 2009-09-15T19:37:12.093 に答える
0

メモリ使用量はおそらく一列に並んでいると思いますが、CPU使用率はそうではありません。

降伏していないスレッドがあるように聞こえます。

于 2009-09-15T19:31:22.480 に答える