Pythonのピクルス可能なオブジェクトの大規模なリストを維持する必要があります。リストが大きすぎてすべてをRAMに保存できないため、データベース/ページングメカニズムが必要です。このメカニズムが、リスト内の近くの(近くの)領域への高速アクセスをサポートする必要があります。
リストはすべてのpython-list機能を実装する必要がありますが、ほとんどの場合、順番に作業します。リスト内のある範囲をスキャンし、スキャン中にスキャンポイントにノードを挿入/ポップするかどうかを決定します。
リストは非常に大きくなる可能性があり(2〜3 GB)、一度にすべてをRAMに含めるべきではありません。ノードは小さい(100〜200バイト)が、さまざまなタイプのデータを含めることができます。
これに対する良い解決策は、最後にアクセスされたバケットのみがRAMにロードされるBTreeを使用することです。
複雑なインデックスキーメカニズムを実装する必要があるため、SQLテーブルの使用は適切ではありません。私のデータはテーブルではなく、特定のインデックスに要素を追加したり、特定の位置から要素をポップしたりする機能を備えた単純なPythonリストです。
ZODBデータベースファイルに保存できるBTreeベースのリストを実装するZODBとzc.blistを試しましたが、上記の機能が妥当な時間で実行されるように構成する方法がわかりません。すべてのマルチスレッド/トランザクション機能は必要ありません。私のシングルスレッドプログラムを除いて、他の誰もデータベースファイルに触れません。
上記の機能が高速に実行されるようにZODB\zc.blistを構成する方法を誰かに説明してもらえますか、それとも別の大規模なリストの実装を見せてもらえますか?
私が試したいくつかの簡単で汚いコード:
import time
import random
NODE_JUMP = 50000
NODE_ACCESS = 10000
print 'STARTING'
random_bytes = open('/dev/urandom', 'rb')
my_list = list()
nodes_no = 0
while True:
nodes_no += NODE_JUMP
start = time.time()
my_list.extend(random_bytes.read(100) for i in xrange(NODE_JUMP))
print 'extending to %s nodes took %.2f seconds' % (nodes_no, time.time() - start)
section_start = random.randint(0, nodes_no -NODE_ACCESS -1)
start = time.time()
for index in xrange(section_start, section_start + NODE_ACCESS):
# rotate the string
my_list[index] = my_list[index][1:] + my_list[index][0]
print 'access to %s nodes took %.2f seconds' % (NODE_ACCESS, time.time() - start,)
印刷は次で終了しました:
5000000ノードへの拡張には3.49秒かかりました 10000ノードへのアクセスには0.02秒かかりました 5050000ノードへの拡張には3.98秒かかりました 10000ノードへのアクセスには0.01秒かかりました 5100000ノードへの拡張には2.54秒かかりました 10000ノードへのアクセスには0.01秒かかりました 5150000ノードへの拡張には2.19秒かかりました 10000ノードへのアクセスには0.11秒かかりました 5200000ノードへの拡張には2.49秒かかりました 10000ノードへのアクセスには0.01秒かかりました 5250000ノードへの拡張には3.13秒かかりました 10000ノードへのアクセスには0.05秒かかりました 殺された(私ではない)