メモリを節約できるアイデアが 1 つだけあります。
データを元のファイルに残したままにして、インメモリ構造からそれらを指すだけにすることができます。
たとえば、大きなログ ファイルをほぼ瞬時に参照するために行うことです。ログ ファイルの内容をメモリ マップし、それをすばやく解析してメモリ内に有用な情報のインデックスを作成し、内容を動的に読み取ります。読み取り中に文字列は作成されません。必要なインデックスを含む動的配列を使用して、各行の先頭へのポインターのみ。呼び出しTStringList.LoadFromFile
は明らかに遅くなり、メモリを消費します。
コードはここにあります-TSynLogFile
クラスを参照してください。秘訣は、ファイルを 1 回だけ読み取り、その場ですべてのインデックスを作成することです。
たとえば、UTF-8 ファイルのコンテンツからテキスト行を取得する方法は次のとおりです。
function TMemoryMapText.GetString(aIndex: integer): string;
begin
if (self=nil) or (cardinal(aIndex)>=cardinal(fCount)) then
result := '' else
result := UTF8DecodeToString(fLines[aIndex],GetLineSize(fLines[aIndex],fMapEnd));
end;
JSON コンテンツを解析するために、まったく同じトリックを使用します。このような混合アプローチの使用は、最速の XML アクセス ライブラリで使用されます。
高レベルのデータを処理し、それらを高速にクエリするには、レコードの動的配列と、最適化されたラッパー (同じユニット内) を使用してみてTDynArray
くださいTDynArrayHashed
。レコードの配列はメモリの消費が少なくなり、データが断片化されないため検索が高速になり (順序付けられたインデックスまたはハッシュを使用するとさらに高速になります)、コンテンツへの高レベルのアクセスが可能になります。 (たとえば、カスタム関数を定義して、メモリ マップ ファイルからデータを取得できます)。動的配列はアイテムの高速削除には適合しません (または、ルックアップ テーブルを使用する必要があります) - しかし、多くのデータを削除していないと書いているので、問題にはなりません。
そのため、構造が重複することはなくなり、ロジックは RAM 内にあり、データはメモリ マップト ファイル上にあります。同じロジックが複数のソース データ ファイルに完全にマップされる可能性があるため、ここに「s」を追加しました (必要な場合)。いくつかの「マージ」と「ライブリフレッシュ」AFAIK)。