Если у меня есть список (или массив, словарь....) в Python, который мог бы превысить доступное пространство адреса памяти, (Python на 32 бита), каковы опции и там относительные скорости? (кроме не вхождения в список, настолько большой), список мог превысить память, но у меня нет способа знать перед рукой. После того как это запускает чрезмерные 75%, которые я хотел бы больше не сохранить списком в памяти (или новые объекты так или иначе), есть ли способ преобразовать в основанную на файле середину реки подхода?
Что является лучшим (скорость в и) опции хранилища файлов?
Просто должен сохранить простой список чисел. никакая потребность к случайному Энному доступу элемента, просто добавьте/вытолкайте операции типа.
Если ваши "числа" достаточно просты (подписанные или неподписанные целые числа до 4 байт каждое, или с плавающей точкой по 4 или 8 байт каждое), я рекомендую стандартную библиотеку array module как лучший способ сохранить несколько миллионов из них в памяти ("tip" вашего "виртуального массива") с бинарным файлом (открытым для бинарного R/W), поддерживающим остальную часть структуры на диске. array.array
имеет очень быстрые методы из файла
и tofile
для облегчения перемещения данных туда и обратно.
т.е, в основном, предполагая, например, беззнаковые длинные числа, что-то вроде:
import os
# no more than 100 million items in memory at a time
MAXINMEM = int(1e8)
class bigarray(object):
def __init__(self):
self.f = open('afile.dat', 'w+')
self.a = array.array('L')
def append(self, n):
self.a.append(n)
if len(self.a) > MAXINMEM:
self.a.tofile(self.f)
del self.a[:]
def pop(self):
if not len(self.a):
try: self.f.seek(-self.a.itemsize * MAXINMEM, os.SEEK_END)
except IOError: return self.a.pop() # ensure normal IndexError &c
try: self.a.fromfile(self.f, MAXINMEM)
except EOFError: pass
self.f.seek(-self.a.itemsize * MAXINMEM, os.SEEK_END)
self.f.truncate()
return self.a.pop()
Конечно, вы можете добавлять другие методы по мере необходимости (например, отслеживать общую длину, добавлять extension
, что угодно), но если pop
и append
действительно все, что вам нужно, это должно служить.
Вероятно, существуют десятки способов хранения данных вашего списка в файле, а не в памяти. То, как вы решите это сделать, будет полностью зависеть от того, какие операции нужно выполнить с данными. Вам нужен случайный доступ к N-му элементу? Вам нужно выполнить итерацию по всем элементам? Будете ли вы искать элементы, которые соответствуют определенным критериям? Какую форму принимают элементы списка? Вы будете вставлять только в конце списка, или также в середине? Есть ли метаданные, которые вы можете хранить в памяти с большей частью элементов на диске? И так далее и так далее
Одна из возможностей - это структурировать ваши данные относительно друг друга и хранить их в базе данных SQLite
.Ну, если вы ищете скорость и ваши данные числовые по своей природе, то вы можете рассмотреть возможность использования numpy и PyTables или h5py. Насколько я помню, интерфейс не так хорош, как простые списки, но масштабируемость просто фантастическая!
.Проверили ли вы полочный питоновый модуль, основанный на огурце?
Возможно, вы захотите рассмотреть другой вид структуры: не список, а придумывание, как сделать (свою задачу) с генератором или пользовательским итератором
. А как насчет базы данных, ориентированной на документы?
Есть несколько альтернатив; я думаю, что самая известная на данный момент - это CouchDB, но вы также можете выбрать Tokyo Cabinet, или MongoDB. Последний имеет преимущество переплетения питона непосредственно из основного проекта, не требуя дополнительного модуля.
Современные операционные системы справятся с этим за вас, не беспокоясь об этом. Это называется виртуальной памятью .
Ответ очень "зависит от обстоятельств".
Что вы храните в списках? Струны? целые числа? Объекты?
Как часто список записывается по сравнению с тем, как его читают? Добавляются ли элементы только в конец, или записи могут быть изменены или вставлены в середину?
Если вы добавляете только в конец, запись в плоский файл может быть самой простой вещью, которая могла бы сработать.
Если вы храните объекты переменного размера, такие как строки, то, возможно, сохраните в памяти индекс начала каждой строки, чтобы вы могли быстро ее прочитать.
Если вам нужно поведение словаря, посмотрите на модули db - dbm, gdbm, bsddb и т. Д.
Если вам нужна запись с произвольным доступом, тогда, возможно, база данных SQL может быть лучше.
Что бы вы ни делали, переход на диск будет на порядки медленнее, чем в памяти, но, не зная, как данные будут использоваться, невозможно быть более конкретным.
редактировать: Исходя из ваших обновленных требований, я бы выбрал плоский файл и сохранил буфер в памяти из последних N элементов.