Буфер Python, который вы можете обрезать слева? - PullRequest
2 голосов
/ 17 июня 2009

Прямо сейчас я буферирую байты, используя строки, StringIO или cStringIO. Но мне часто нужно удалять байты с левой стороны буфера. Наивный подход перестроил бы весь буфер. Есть ли оптимальный способ сделать это, если усечение слева является очень распространенной операцией? Сборщик мусора в Python должен на самом деле собирать усеченные байты.

Любой алгоритм для этого (хранить буфер небольшими частями?) Или существующая реализация действительно помогли бы.

Edit:

Я пытался использовать для этого представление памяти Python 2.7, но, к сожалению, данные вне «представления» не GCed при удалении исходной ссылки:

# (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 '.',

Ответы [ 2 ]

3 голосов
/ 17 июня 2009

A deque будет эффективен при частых операциях удаления влево (в отличие от использования списка, строки или буфера, амортизируется O (1) для удаления с любого конца). Однако это будет более затратно с точки зрения памяти, чем строка, поскольку каждый символ будет храниться как отдельный строковый объект, а не как упакованная последовательность.

В качестве альтернативы, вы можете создать свою собственную реализацию (например, связанный список строковых / буферных объектов фиксированного размера), который может хранить данные более компактно.

1 голос
/ 17 июня 2009

Создайте свой буфер как список символов или строк и нарежьте список. Присоединяйтесь только как строка на выходе. Это довольно эффективно для большинства типов поведения «изменяемой строки».

GC будет собирать усеченные байты, поскольку на них больше нет ссылок в списке.

ОБНОВЛЕНИЕ: Для изменения заголовка списка вы можете просто перевернуть список. Это звучит как неэффективная вещь, однако реализация списка python оптимизирует это внутренне.

из http://effbot.org/zone/python-list.htm:

Реверсирование быстрое, поэтому временно изменение списка часто может ускорить вещи, если вам нужно удалить и вставить кучу предметов на начало списка:

L.reverse()
# append/insert/pop/delete at far end
L.reverse()
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...