C malloc/free + fgets のパフォーマンス
-
13-09-2019 - |
質問
ファイル A 内の行をループしながら、その行を解析し、各文字列 (char*
) に char**
.
行の最後で、次を使用してファイル B を開く手順を実行します。 fgets
, fseek
そして fgetc
そのファイルから文字を取得します。次に、ファイル B を閉じます。
ファイル B を 1 行ずつ開いたり閉じたりを繰り返します。
私が知りたいのは次のとおりです。
を使用することでパフォーマンスに重大な影響がありますか?
malloc
そしてfree
, 、次のような静的なものを使用する必要がありますmyArray[NUM_STRINGS][MAX_STRING_WIDTH]
ダイナミックの代わりにchar** myArray
?ファイル B の開閉 (概念的には何千回も) による重大なパフォーマンスのオーバーヘッドはありますか?ファイル A がソートされている場合、使用する方法はありますか?
fseek
ファイル B を「後方」に移動するには、ファイル B 内で以前に位置していた場所をリセットするには?
編集 次の 2 つのアプローチにより、実行時間が大幅に短縮されることがわかりました。
私のファイル B は、実際には 24 個のファイルのうちの 1 つです。同じファイル B1 を 1,000 回開き、次に B2 を 1,000 回開くのではなく、ファイル B1 を 1 回開いて閉じ、B2 を 1 回開いて閉じる、というように繰り返します。これにより、何千ものコストが削減されます
fopen
そしてfclose
およそ24までの操作。私が使用した
rewind()
ファイルポインタをリセットします。
これにより、約 60 倍の速度向上が得られ、十分以上です。教えてくれてありがとう rewind()
.
解決
、いくつかのrealloc
s上のコピーコストがあります。あなたは「常に二重の」ヒューリスティックを使用している場合、これはO(n)の償却、それは恐ろしいではありません。あなたが先に時間の大きさを知っている場合、スタックに割り当てられた配列は、まだ速くなります。
は、2番目の質問についてrewind
について読みました。それはすべての時間を開閉するよりも高速になった、とあなたはより少ないリソース管理を行うことができますしています。
他のヒント
私が知りたいのは次のとおりです。
- コードは正しく動作しますか?
- 目的に応じて十分な速度で動作していますか?
これら両方の答えが「はい」の場合は、何も変更しないでください。
開閉は、他のプログラムがそのリソースのcompetitngされている場合に応じて可変オーバーヘッドを有している。
の の最初のファイルのサイズを測定して、一つの大きなヒープ割り当てを行うには、事前に配列サイズを計算するためにそれを使用ます。
あなたは右オフ多次元配列を得るが、ポインタ演算のビットとあなたがそこにいることはありません。
あなたは他のファイルに位置情報をキャッシュすることはできませんし、オフセットのように、むしろそれを開閉するよりも、以前使用してインデックスを求めますか?本当に正確なロジックに依存します。
ファイルが大きい場合、ディスク I/O はメモリ管理よりもはるかに高価になります。プロファイリング前に malloc/free のパフォーマンスを心配することは、それが時期尚早の最適化がボトルネックであることを示しています。
プログラム内で頻繁にオープン/クローズすることによるオーバーヘッドが大きい可能性がありますが、ファイルが小さい場合を除き、やはり実際の I/O はより高価になる可能性が高く、その場合、クローズとオープンの間でバッファーが失われる可能性があります。余分なディスク I/O が発生します。そしてはい、 ftell() を使用してファイル内の現在位置を取得し、SEEK_SET で fseek を使用してそこに到達することができます。
は常に動的メモリを使用すると、パフォーマンスヒットがあります。静的バッファを使用すると、スピードブーストを提供します。
また、ファイルを再度開くとパフォーマンスヒットがあるように起こっています。あなたは相対的な移動を行うために(、SEEK_CURオフセット)ファイルまたはfseek関数内の任意の位置にファイルポインタを設定するのfseek(POS、SEEK_SET)を使用することができます。
大幅なパフォーマンスのヒットは相対的であり、あなたはそれが自分のために何を意味するのかを決定する必要があります。
割り当てた方が良いと思います 必要な実際のスペースと、 オーバーヘッドはおそらく 重要な。これにより、両方が回避されます スペースの浪費とスタックオーバーフロー
はい。IOはキャッシュされていますが、不必要なsyscallsを作成しています(開閉)。おそらくfseekを使用してください
SEEK_CUR
またはSEEK_SET
.
どちらの場合も、 いくつかの パフォーマンスは低下しますが、その重要性はファイルのサイズとプログラムが実行されるコンテキストによって異なります。
実際に文字列の最大数と最大幅を知っている場合、これははるかに高速になります (ただし、「最大」未満を使用すると、大量のメモリを浪費する可能性があります)。幸せな手段は、C++ の動的配列の多くの実装と同じことを行うことです。myArray を再割り当てする必要がある場合は、必要なスペースの 2 倍のスペースを割り当て、スペースがなくなった場合にのみ再割り当てしてください。これには O(log n) のパフォーマンス コストがかかります。
これはパフォーマンスに大きな影響を与える可能性があります。詳細はアルゴリズムによって異なりますが、fseek を使用することを強くお勧めします。
私は、多くの場合、パフォーマンスのオーバーヘッドがメモリ上malloc
、それらの低レベルのC・ハンドラが付属してダイレクトメモリ管理が勝ることを見つけます。メモリのこれらの領域は、このメモリに触れるよりも大きい償却時間である時間の量のための静的および手付かずのままとしている場合を除き、静的配列に固執する方が有益であろう。最後に、それはあなた次第です。