Производительность соединения строки python

В Интернете много статей о производительности python, первое, что вы читаете: конкатенировать строки не следует, используя "+": избегать s1 + s2 + s3, вместо этого использовать str.join

Я пробовал следующее: конкатенация двух строк как часть пути к каталогу: три подхода:

  • '+', который я не должен делать
  • str.join
  • os.path.join

Вот мой код:

import os,time

s1='/part/one/of/dir'
s2='part/two/of/dir'
N=10000

t=time.clock()
for i in xrange(N):
    s=s1+os.sep+s2
print time.clock()-t

t=time.clock()
for i in xrange(N):
    s=os.sep.join((s1,s2))
print time.clock()-t

t=time.clock()
for i in xrange(N):
    s=os.path.join(s1,s2)
print time.clock()-t

Здесь результаты (python 2.5 WinXP)

0.0182201927899
0.0262544541275
0.120238186697

Разве это не должно быть наоборот?

Ответ 1

Правда, вы не должны использовать '+'. Ваш пример довольно особенный, попробуйте тот же код с помощью:

s1='*'*100000
s2='+'*100000

Затем вторая версия (str.join) выполняется намного быстрее.

Ответ 2

Большинство проблем производительности при конкатенации строк являются характеристиками асимптотической производительности, поэтому различия становятся наиболее значительными, когда вы объединяете многие длинные строки. В вашем примере вы выполняете одну и ту же конкатенацию много раз. Вы не создаете длинную строку, и может быть, что интерпретатор python оптимизирует ваши циклы. Это объясняет, почему время увеличивается, когда вы переходите на str.join и path.join - это более сложные функции, которые не так легко сокращаются. (os.path.join делает много проверок на строках, чтобы увидеть, нужно ли их переписывать каким-либо образом, прежде чем они будут объединены. Это приносит в жертву некоторую производительность ради мобильности.)

Кстати, поскольку пути к файлам обычно не очень длинные, вы почти наверняка хотите использовать os.path.join ради переносимости. Если производительность конкатенации является проблемой, вы делаете что-то очень странное с вашей файловой системой.

Ответ 3

Разве это не должно быть наоборот?

Не обязательно. Я не знаю внутренних компонентов Python достаточно хорошо, чтобы прокомментировать, но некоторые общие наблюдения заключаются в том, что ваш первый цикл использует простой оператор +, который, вероятно, реализован как примитив во время выполнения. Напротив, другие петли сначала должны решить имя модуля, разрешить найденную там переменную/класс, а затем вызвать функцию-член.

Еще одно замечание: ваш цикл может быть слишком мал, чтобы давать значительные числа. Учитывая низкое общее время работы, это, вероятно, делает ваши тесты бесполезными.

Кроме того, ваш тестовый пример очень специализирован на двух коротких строках. Такие случаи никогда не дают четкого представления о производительности кромки.

Ответ 4

Совет о конкатенировании множества строк.

Для вычисления s = s1 + s2 +... + sn,

1), используя+. Создается новая строка s1 + s2, затем создается новая строка s1 + s2 + s3,... и т.д., Поэтому задействовано много операций по распределению памяти и копированию. Фактически, s1 копируется n-1 раз, s2 копируется n-2 раз,... и т.д.

2), используя "".join([s1, s2,..., sn]). Конкатенация выполняется за один проход, и каждый char в строках копируется только один раз.

В вашем коде соединение вызывается на каждой итерации, поэтому оно просто похоже на+. Правильный способ - собрать элементы в массиве, а затем вызвать соединение на нем.

edit: исправлена ​​опечатка

Ответ 5

Конкатенация строк (+) имеет оптимизированную реализацию на CPython. Но это может быть не так на других архитектурах, таких как Jython или IronPython. Поэтому, когда вы хотите, чтобы ваш код хорошо работал на этих интерпретаторах, вы должны использовать метод .join() для строк. os.path.join() специально предназначен для присоединения к путям файловой системы. Он также заботится о разных разделителях пути. Это будет правильным способом для создания имени файла.

Ответ 6

Я хотел бы добавить ссылку на вики python, где есть примечания о конкатенации строк, а также о том, что "этот раздел несколько неправилен с python2.5. Конкатенация строк Python 2.5 довольно быстро".

Я считаю, что объединение строк с большим успехом улучшилось с 2.5, и хотя str.join все еще быстрее (особенно для больших строк), вы не увидите такого улучшения, как в старых версиях Python.

http://wiki.python.org/moin/PythonSpeed/PerformanceTips#StringConcatenation