Низкая производительность, которую вы наблюдаете, вызвана ошибкой в сборщике мусора Python в используемой вами версии. Обновите до Python 2.7 или 3.1 или выше, чтобы восстановить ожидаемое поведение 0 (1) с амортизацией. добавления списка в Python.
Если вы не можете выполнить обновление, отключите сборку мусора при создании списка и включите его после завершения.
(Вы также можете настроить триггеры сборщика мусора или выборочно вызвать сборщик по мере продвижения, но я не рассматриваю эти варианты в этом ответе, поскольку они более сложны, и я подозреваю, что ваш вариант использования подпадает под приведенное выше решение.)
Справочная информация:
См .: https://bugs.python.org/issue4074, а также https://docs.python.org/release/2.5.2/lib/module-gc.html
Репортер отмечает, что добавление сложных объектов (объектов, которые не являются числами или строками) в список линейно замедляется по мере увеличения длины списка.
Причиной такого поведения является то, что сборщик мусора проверяет и перепроверяет каждый объект в списке, чтобы определить, имеют ли они право на сборку мусора. Такое поведение вызывает линейное увеличение времени для добавления объектов в список. Ожидается, что исправление появится в py3k, поэтому оно не должно применяться к используемому вами переводчику.
Тест:
Я провел тест, чтобы продемонстрировать это. Для 1k итераций я добавляю 10k объектов в список и записываю время выполнения для каждой итерации. Общая разница во времени выполнения очевидна. Если во время внутреннего цикла теста сборка мусора отключена, время выполнения в моей системе составляет 18,6 с. Если сборка мусора включена для всего теста, время выполнения составляет 899,4 с.
Это тест:
import time
import gc
class A:
def __init__(self):
self.x = 1
self.y = 2
self.why = 'no reason'
def time_to_append(size, append_list, item_gen):
t0 = time.time()
for i in xrange(0, size):
append_list.append(item_gen())
return time.time() - t0
def test():
x = []
count = 10000
for i in xrange(0,1000):
print len(x), time_to_append(count, x, lambda: A())
def test_nogc():
x = []
count = 10000
for i in xrange(0,1000):
gc.disable()
print len(x), time_to_append(count, x, lambda: A())
gc.enable()
Полный источник: https://hypervolu.me/~erik/programming/python_lists/listtest.py.txt
Графический результат: красный с включенным gc, синий с выключенным gc. Ось Y - это логарифмическое масштабирование секунд.

(источник: hypervolu.me )
Поскольку эти два графика отличаются на несколько порядков величины по компоненте y, здесь они независимо, а ось y линейно масштабируется.

(источник: hypervolu.me )

(источник: hypervolu.me )
Интересно, что при отключенной сборке мусора мы видим только небольшие всплески времени выполнения на 10 тыс. Добавлений, что говорит о том, что затраты на перераспределение списков в Python относительно невелики. В любом случае они на много порядков ниже затрат на сборку мусора.
Плотность вышеприведенных графиков затрудняет понимание того, что при включенном сборщике мусора большинство интервалов действительно имеют хорошую производительность; только когда циклы сборщика мусора встречаются с патологическим поведением. Вы можете наблюдать это на гистограмме времени добавления 10 тыс. Большинство точек данных падает около 0,02 с на 10 тыс. Добавлений.

(источник: hypervolu.me )
Необработанные данные, использованные для составления этих графиков, можно найти по адресу http://hypervolu.me/~erik/programming/python_lists/