2

現在、文字列、StringIO、または cStringIO を使用してバイトをバッファリングしています。しかし、多くの場合、バッファーの左側からバイトを削除する必要があります。単純なアプローチでは、バッファ全体が再構築されます。左切り捨てが非常に一般的な操作である場合、これを行う最適な方法はありますか? Python のガベージ コレクターは、切り捨てられたバイトを実際に GC する必要があります。

これのためのアルゴリズム(バッファを小さな断片に保ちますか?)、または既存の実装が本当に役に立ちます。

編集:

これには Python 2.7 のメモリビューを使用しようとしましたが、残念ながら、元の参照が削除されると、「ビュー」の外側のデータは GC されません。

# (This will use ~2GB of memory, not 50MB)

memoryview # Requires Python 2.7+

smalls = []

for i in xrange(10):
    big = memoryview('z'*(200*1000*1000))
    small = big[195*1000*1000:]
    del big
    smalls.append(small)
    print '.',
4

2 に答える 2

3

左削除操作が頻繁に行われる場合、両端キューは効率的です(リスト、文字列、またはバッファーを使用する場合とは異なり、両端キューはO(1)で償却されます)ただし、各文字をパックされたシーケンスではなく独自の文字列オブジェクトとして格納するため、文字列よりもメモリのコストが高くなります。

または、独自の実装(たとえば、固定サイズの文字列/バッファオブジェクトのリンクリスト)を作成して、データをよりコンパクトに保存することもできます。

于 2009-06-17T11:49:41.343 に答える
1

文字または行のリストとしてバッファーを作成し、リストをスライスします。出力時に文字列としてのみ結合します。これは、ほとんどの種類の「変更可能な文字列」の動作に対して非常に効率的です。

GC は切り捨てられたバイトを収集します。これは、それらがリストで参照されなくなったためです。

更新: リスト ヘッドを変更するには、リストを逆にするだけです。これは非効率的なことのように思えますが、Python のリスト実装はこれを内部的に最適化します。

http://effbot.org/zone/python-list.htmから:

リバースは高速なので、リストの先頭にある一連の項目を削除および挿入する必要がある場合は、リストを一時的にリバースすると速度が向上することがよくあります。

L.reverse()
# append/insert/pop/delete at far end
L.reverse()
于 2009-06-17T10:25:03.340 に答える