SQlite データベースからバイナリ データの任意のサイズ (ただし、通常は小さい) のチャンクを読み取る必要がある状況があります。データベースはディスク上に存在し、データは ID と 256 ~ 64k バイトの読み取り専用 BLOB で構成される行に格納されます (長さは常に 2 の累乗になります)。SQlite のインクリメンタル I/Oを使用して、チャンクを書き換え可能なバッファーに読み込み、チャンク内の値の平均を取り、結果をキャッシュします。
私が抱えている問題は、チャンクが任意のサイズであるため、ブロブのサイズがチャンクのサイズの整数倍になることはほとんどないということです。これは、チャンクが 2 つの BLOB に頻繁にまたがることを意味します。
私が探しているのは、このやや厄介なシナリオを処理するためのシンプルでエレガントな (「エレガンスはオプションではない」ため) 方法です。read-chunk
チャンクを読み取って平均を計算するだけの、かなり馬鹿げた関数があります。これまでのところ、次の戦略を試しました。
- 重複するチャンクの最初の部分のみを読み取り、2 番目の部分を破棄します。
read-chunk
適切な場所で次のブロブに移動できるように、ブロブの境界に注意してください。- リング バッファーのようなものを使用して、オーバーラップするチャンクがエッジをラップできるようにします。
最初のオプションは最も単純ですが、潜在的に重要な情報を破棄するため、不十分です。は頻繁に呼び出されるのでread-chunk
、あまりにも多くの分岐ロジックで負担をかけたくないので、2 番目のオプションも魅力的ではありません。リング バッファ (またはそのようなもの) を使用することは、洗練されたソリューションのように思えます。私が想定しているのは、中間サイズ (たとえば 256 バイト) のチャンクをブロブから 1k バッファーに読み取るプロデューサーと、read-chunk
バッファーを呼び出して適切な場所でラップするコンシューマーです。私は常に 2 のべき乗を扱うため、プロデューサーは常にバッファーの端に揃えられますmod
。また、プロデューサーとコンシューマーの両方のインデックスを計算するために使用することを避けることもできます。
私は Lisp (CL) を使用していますが、これは一般的なアルゴリズムまたはデータ構造の問題のように思われるため、言語に依存しないままにしています。私が興味を持っているのは、私が持っているオプションを明確にすることです-私がリストしたもの以外に別のオプションはありますか?