много идей. Однако, если вам нужна практическая помощь, отредактируйте свой вопрос, чтобы показать ВСЕ ваш код. Также скажите нам, что это «оно», которое показывает используемую память, что оно показывает, когда вы загружаете файл с нулевым количеством записей, и на какой платформе вы находитесь, и какую версию Python.
Вы говорите, что "слово может быть длиной 1-5 слов". Какова средняя длина ключевого поля в байтах? Все ли идентификаторы целые? Если да, каковы минимальное и максимальное целое число? Если нет, какова средняя длина, если идентификатор в байтах? Чтобы включить перекрестную проверку всего вышеперечисленного, сколько байтов содержится в файле строки размером 6,5 мегабайта?
Глядя на ваш код, файл из одной строки word1,1
создаст дикт d['1'] = 'word1'
... разве это не баснословно?
Обновление 3: дополнительные вопросы: как закодировано слово? Вы уверены, что ни на одном из двух полей не загружены пробелы в конце?
Обновление 4 ... Вы спросили ", как наиболее эффективно хранить пары ключ / значение в памяти с python " и , но никто не ответил на этот вопрос с какой-либо точностью .
У вас есть файл 168 Мб с 6,5 миллионами строк. Это 168 * 1,024 ** 2 / 6,5 = 27,1 байта на строку. Отбросьте 1 байт для запятой и 1 байт для новой строки (при условии, что это * x платформа), и у нас осталось 25 байт на строку. Предполагая, что «id» предназначен для того, чтобы быть уникальным, и, поскольку он выглядит как целое число, давайте предположим, что «id» имеет длину 7 байтов; это оставляет нас со средним размером 18 байт для слова. Это соответствует вашим ожиданиям?
Итак, мы хотим сохранить 18-байтовый ключ и 7-байтовое значение в таблице поиска в памяти.
Предположим, 32-битная платформа CPython 2.6.
>>> K = sys.getsizeof('123456789012345678')
>>> V = sys.getsizeof('1234567')
>>> K, V
(42, 31)
Обратите внимание, что sys.getsizeof(str_object) => 24 + len(str_object)
Кортежи были упомянуты одним ответчиком. Обратите внимание на следующее:
>>> sys.getsizeof(())
28
>>> sys.getsizeof((1,))
32
>>> sys.getsizeof((1,2))
36
>>> sys.getsizeof((1,2,3))
40
>>> sys.getsizeof(("foo", "bar"))
36
>>> sys.getsizeof(("fooooooooooooooooooooooo", "bar"))
36
>>>
Вывод: sys.getsizeof(tuple_object) => 28 + 4 * len(tuple_object)
... он позволяет только указатель на каждый элемент, он не учитывает размеры элементов.
Аналогичный анализ списков показывает, что sys.getsizeof(list_object) => 36 + 4 * len(list_object)
... опять же необходимо добавить размеры предметов. Существует еще одно соображение: CPython перераспределяет списки, чтобы он не вызывал систему realloc () при каждом вызове list.append (). Для достаточно большого размера (например, 6,5 миллиона!) Общее распределение составляет 12,5 процента - см. Источник (Objects / listobject.c). Это перераспределение не выполняется с кортежами (их размер не изменяется).
Вот затраты на различные альтернативы для таблицы поиска на основе памяти:
Список кортежей:
Каждый кортеж будет принимать 36 байтов для самого кортежа, плюс K и V для содержимого. Так что N из них займет N * (36 + K + V); тогда вам нужен список для их хранения, поэтому нам нужно 36 + 1,125 * 4 * N для этого.
Всего для списка кортежей: 36 + N * (40,5 + K + v)
Это 26 + 113,5 * N ( около 709 МБ , когда 6,5 миллиона)
Два параллельных списка:
(36 + 1,125 * 4 * N + K * N) + (36 + 1,125 * 4 * N + V * N)
то есть 72 + N * (9 + K + V)
Обратите внимание, что разница между 40,5 * N и 9 * N составляет около 200 МБ, когда N составляет 6,5 млн.
Значение хранится как int, а не str:
Но это еще не все. Если идентификаторы на самом деле являются целыми числами, мы можем сохранить их как таковые.
>>> sys.getsizeof(1234567)
12
Это 12 байтов вместо 31 байта для каждого объекта значения. Эта разница в 19 * N означает дальнейшую экономию около 118 МБ, когда N составляет 6,5 млн.
.
Использовать array.array ('l') вместо списка для (целого) значения:
Мы можем хранить эти 7-значные целые числа в array.array ('l'). Нет int-объектов и указателей на них - только 4-байтовое целочисленное значение со знаком. Бонус: массивы перераспределены только на 6,25% (для больших N). Таким образом, это 1,0625 * 4 * N вместо предыдущего (1,125 * 4 + 12) * N, дальнейшая экономия составляет 12,25 * N, то есть 76 МБ.
Итак, мы сократились до 709 - 200 - 118 - 76 = около 315 МБ .
N.B. За исключением ошибок и пропусков - это 0127 в моем TZ :-(