Почему a.insert (0,0) намного медленнее, чем [0: 0] = [0]? - PullRequest
61 голосов
/ 29 февраля 2020

Использование функции списка insert намного медленнее, чем достижение того же эффекта с помощью назначения срезов:

> python -m timeit -n 100000 -s "a=[]" "a.insert(0,0)"
100000 loops, best of 5: 19.2 usec per loop

> python -m timeit -n 100000 -s "a=[]" "a[0:0]=[0]"
100000 loops, best of 5: 6.78 usec per loop

(Обратите внимание, что a=[] является только настройкой, поэтому a начинается пустым, но затем увеличивается до 100 000 элементов.)

Сначала я подумал, может быть, это поиск атрибута или служебный вызов функции или около того, но вставка в конце показывает, что это незначительно:

> python -m timeit -n 100000 -s "a=[]" "a.insert(-1,0)"
100000 loops, best of 5: 79.1 nsec per loop

Почему предположительно более простая выделенная функция «вставка одного элемента» намного медленнее?

Я также могу воспроизвести ее в repl.it :

from timeit import repeat

for _ in range(3):
  for stmt in 'a.insert(0,0)', 'a[0:0]=[0]', 'a.insert(-1,0)':
    t = min(repeat(stmt, 'a=[]', number=10**5))
    print('%.6f' % t, stmt)
  print()

# Example output:
#
# 4.803514 a.insert(0,0)
# 1.807832 a[0:0]=[0]
# 0.012533 a.insert(-1,0)
#
# 4.967313 a.insert(0,0)
# 1.821665 a[0:0]=[0]
# 0.012738 a.insert(-1,0)
#
# 5.694100 a.insert(0,0)
# 1.899940 a[0:0]=[0]
# 0.012664 a.insert(-1,0)

Я использую Python 3.8.1 32-битный на Windows 10 64-битный.
repl.it использует Python 3.8.1 64-битный на Linux 64-битный.

1 Ответ

57 голосов
/ 29 февраля 2020

Я думаю, возможно, они просто забыли использовать memmove в list.insert. Если вы посмотрите на код list.insert, используемый для смещения элементов, вы увидите, что это просто руководство l oop:

for (i = n; --i >= where; )
    items[i+1] = items[i];

, а list.__setitem__ на слайсе путь назначения использует memmove:

memmove(&item[ihigh+d], &item[ihigh],
    (k - ihigh)*sizeof(PyObject *));

memmove, как правило, имеет много оптимизаций, таких как использование инструкций SSE / AVX.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...