タスクは、バイナリ ファイルをメモリに解析することです。ただし、割り当てに必要なメモリの量はアプリオリにはわかりません。
解析ルーチンの進行に合わせて複数の小さな malloc を実行するか、必要なメモリ量を決定するために最初にファイルを走査してから再度解析するか、どちらの方法が望ましいとされていますか?
どんなヒントでも大歓迎です。
タスクは、バイナリ ファイルをメモリに解析することです。ただし、割り当てに必要なメモリの量はアプリオリにはわかりません。
解析ルーチンの進行に合わせて複数の小さな malloc を実行するか、必要なメモリ量を決定するために最初にファイルを走査してから再度解析するか、どちらの方法が望ましいとされていますか?
どんなヒントでも大歓迎です。
ほとんどの場合、多数の小さな割り当てよりも 1 つの大きな割り当ての方が適切です。これにより、断片化が防止され、システム コールが少なくなります。多くの場合、より優れた局所性によってパフォーマンスが向上します。
一般的な手法は、最初に小さなセグメントを割り当て、固定係数 (多くの場合1.5
) によって大きなセグメントを再割り当てすることです。すべての要素が収集された後、過剰割り当てが大きいと見なされる場合は、メモリを最大サイズに固定できます。
いずれにせよ: 最も単純なものを最初に実装します。パフォーマンスに問題がある場合: ベンチマーク。次に最適化します。割り当てがボトルネックでさえないことが判明するかもしれません。
EDIT: R..が言及しているように、メモリの上限とファイル長との関係について推論することで、どれだけ割り当てるかについて良い考えが得られるかもしれません。優れたバイナリ形式のほとんどには、ヘッダー セグメントに長さとサイズの情報も含まれています。データ構造に必要な正確なサイズを計算やファイル シークで正確に把握できれば、勝者となります。
これに を使用することを見たことがありますmmap()
か?詳細については、このリンクを参照してください。基本的に、ファイルをメモリにマップし、メモリ ブロックであるかのようにアクセスし、malloc()
s を完全に回避します。
これは、古典的な時空間のトレードオフです。コンテンツ全体が必要であると仮定すると、多数の小さなブロックを割り当てると、1 つの大きなブロックよりも効率が低下する可能性があります。
理想的には、ファイル形式は、ブロックのサイズ、チャンクの数などのメタデータをエンコードする必要があります。メモリの速度と比較してディスク アクセスの待ち時間を考慮すると、ファイルを読み取って必要なサイズを判断するには、より長い時間がかかる可能性があります。
最も効率的な方法は、必要な処理量によっても異なります。あなたは解析について言及していますが、それはバイナリファイルです。おそらく、横断する必要のあるチャンクや可変サイズの構造が多数あるのではないでしょうか?
あなたが試すことができるいくつかの戦略があります:
ファイルが大きすぎてメモリに収まらない場合は、ファイルシステムにクエリを実行してファイルの大きさを確認し、それを 1 つの大きなチャンクとして読み込んでから、メモリ内で引き離すことができます。これは非常に高速ですが、大量のメモリを使用します。
バイナリ ファイルの構造によっては、いくつかのfseek()
呼び出しを実行して、読み取る必要があるチャンクの大きさを把握し (ファイル全体が必要ない場合)、それらを読み取ることができる場合があります。
を使用mmap()
して、ファイルをメモリにマップし、ランタイムがメモリへのデータのページングを管理できるようにすることができます。
ファイルのサイズと必要なメモリの量を決定するためにファイルをトラバースすることは、間違いなく適切な方法ではありません。ディスク I/O は非常に高価です。
もう 1 つのオプションは、ファイル サイズを取得してからメモリを割り当てることです。ファイル サイズの取得方法の詳細については、この Q/Aを参照してください。ただし、この方法も効率的ではありません。
全体として、実際にはデータの読み取り方法と解析方法に依存します。たとえば、非同期ファイル I/O と一緒にいくつかのかなり大きなデータ チャンクを使用すると、最適な結果が得られる場合があります。しかし、それを実装するのは比較的複雑な作業です。
おそらく、最も簡単で非常に効率的な方法mmap
は、ファイルの内容を使用してメモリに「マップ」することです。
「好ましい」を定義していないため、少なくとも部分的には一般的な答えはありません。最も簡単ですか?最速?最小限のヒープが必要ですか? また、「バイナリファイルを解析する」とはどういう意味ですか? 解析は通常、データ構造を作成するために、人間が判読できるテキストに対して実行されるものです。
通常、それぞれmalloc
に小さなオーバーヘッドがあります。ただし、最終的なデータ構造が巨大でない限り、大きな違いが生じる可能性は低いです。
明確なインターフェイスを使用して、最も明確なコードを生成することを行い、後で割り当て方法を置き換えることができます。次に、問題があることがわかった後でのみ、最適化について心配します。