まず、単一の大きなファイルを65536の小さなファイルに分割します。これにより、ハッシュが0000
ファイル内00/00data.txt
にある場合、ハッシュがファイル内にある場合など0001
になります。ファイル00/01data.txt
全体が12 GiBの場合、各ファイルは小さいファイルは(平均で)208KiBになります。
次に、文字列からハッシュを分離します。65536の「ハッシュファイル」と65536の「文字列ファイル」があります。各ハッシュファイルには、残りのハッシュ(最初の4桁は不要になったため、最後の12桁のみ)と、対応する文字列ファイル内の文字列のオフセットが含まれます。これは、(それぞれ平均208 KiBの65536ファイルではなく)それぞれ120KiBの65536ハッシュファイルと100KiBの65536文字列ファイルがあることを意味します。
次に、ハッシュファイルはバイナリ形式である必要があります。12桁の16進数は48ビットです(12 * 8 = 96ビットではありません)。これだけで、ハッシュファイルのサイズが半分になります。文字列が文字列ファイルの4バイト境界に配置されている場合、16ビットの「文字列のオフセット/ 4」で問題ありません(文字列ファイルが256 KiB未満である場合)。ハッシュファイルのエントリは順番に並べ替える必要があり、対応する文字列ファイルは同じ順序にする必要があります。
これらすべての変更の後。ハッシュの上位16ビットを使用して、適切なハッシュファイルを見つけ、ハッシュファイルをロードして、バイナリ検索を実行します。次に(見つかった場合)、ハッシュファイルのエントリから(文字列ファイル内の)文字列の開始のオフセットを取得し、さらにハッシュファイルの次のエントリから次の文字列のオフセットを取得します。次に、文字列ファイルからデータをロードします。正しい文字列の先頭から始まり、次の文字列の先頭で終わります。
最後に、メモリに「ハッシュファイルキャッシュ」を実装します。アプリケーションが1.5GiBのRAMを割り当てることができる場合、ハッシュファイルの半分をキャッシュするにはそれで十分です。この場合(キャッシュされたハッシュファイルの半分)、ディスクからロードする必要があるのは文字列自体(おそらく20バイト未満)だけで、残りの半分は最初にハッシュファイルをキャッシュにロードする必要があります(例:60KiB)。したがって、ルックアップごとに平均して、ディスクから約30KiBをロードすることになります。もちろん、メモリが多いほど良いです(そして少ないほど悪いです)。また、約3 GiBを超えるRAMを割り当てることができる場合は、すべてのハッシュファイルをキャッシュして、一部の文字列のキャッシュについて考え始めることができます。
より高速な方法は、可逆エンコーディングを使用することです。これにより、文字列を整数に変換してから、ルックアップをまったく行わずに整数を元の文字列に戻すことができます。例として; すべての文字列が小文字のASCII文字を使用し、最大である場合。13文字の長さの場合、それらはすべて64ビット整数に変換して戻すことができます(26 ^ 13 <2 ^ 63として)。これにより、別のアプローチが可能になる可能性があります。たとえば、可能な場合はリバーシブルエンコーディング(整数/ハッシュクリアのビット64)を使用します。可逆的な方法でエンコードできない文字列には、ある種のルックアップ(整数/ハッシュのビット64が設定されている)のみを使用します。少しの知識があれば(たとえば、文字列に最適なリバーシブルエンコーディングを慎重に選択するなど)、13GiBファイルのサイズを「RAMに簡単に収まるほど小さい」サイズに縮小できます。