Строковая производительность - Python 2.7 против Python 3.4 под Windows 10 против Ubuntu

Случай использования
Простая функция, которая проверяет, находится ли конкретная строка в другой строке в позиции, кратной 3 (см. Здесьпример из реального мира, нахождение стоп-кодонов в последовательности ДНК).

функции
sliding_window: принимает строку длиной 3, сравнивает ее со строкой поиска, если они идентичны, перемещает на 3 символа вперед.
incremental_start: пытается найти строку поиска, если найденная позиция не кратна 3, она пытается найти следующую позицию после найденной позиции.

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

Результаты

Python 2.7: Начальныйsliding_window функция может быть улучшена в ~ 39 раз с помощью функцииincremental_start в Python2.7 на Windows 10. В Ubuntu наблюдалось небольшое снижение производительности, ~ 34x, ~ 37x, ~ 18x (VM, AWS, native), но все еще в том же диапазоне.
Python 3.4: sliding_window стал медленнее, чем в Python2.7 (1.8x в Windows, 1.4x или 1.5x на всех Ubuntus), ноincremental_start производительность снизилась на всех Ubuntus в 4, 5, 1,7 раза (VM, AWS, native), в то время как на Window s она практически не изменилась.Windows против Ubuntu
python2.7: виртуализированной Ubuntus требовалось меньше времени для обеих функций (~ 20-30%), нативная Ubuntu была примерно на 25% медленнее дляincremental_start, в то время какsliding_window был на 40% быстрее.
python3:sliding_window функции потребовалось меньше времени для завершения (~ 50%), в то время какincremental_start стал медленнее в ~ 2-3 раза.

Вопросы

Что вызывает разницу в производительности в Python 2 против Python 3 в Linux против Windows?Как можно предвидеть такое поведение и корректировать код для оптимальной производительности?

Код

import timeit

text = 'ATG' * 10**6
word = 'TAG'

def sliding_window(text, word):
    for pos in range(0, len(text), 3):
        if text[pos:pos + 3] == word:
            return False
    return True

def incremental_start(text, word):
    start = 0
    while start != -1:
        start = text.find(word, start + 1)
        if start % 3 == 0:
            return False
    return True

#sliding window
time = timeit.Timer(lambda: sliding_window(text, word), setup='from __main__ import text, word').timeit(number=10)
print('%3.3f' % time)

#incremental start
time = timeit.Timer(lambda: incremental_start(text, word), setup='from __main__ import text, word').timeit(number=500)
print('%3.3f' % time)

таблицы

Ubuntu vs Windows    VM     AWS    Native   
Python2.7-Increment  79%    73%    126% 
Python2.7-Sliding    70%    70%    60%                  
Python3.4-Increment  307%   346%   201% 
Python3.4-Sliding    54%    59%    48%  

Py2 vs 3    Windows    VM    AWS    Native
Increment   105%       409%  501%   168%
Sliding     184%       143%  155%   147%

Absolute times in seconds
                 Win10   Ubuntu  AWS     Native
Py2.7-Increment  1.759   1.391   1.279   2.215 
Py2.7-Sliding    1.361   0.955   0.958   0.823 

Py3.4-Increment  1.853   5.692   6.406   3.722 
Py3.4-Sliding    2.507   1.365   1.482   1.214 

подробности
Windows 10: родная Windows, 32-битный Python 3.4.3 или 2.7.9, i5-2500, 16 ГБ ОЗУ
Виртуальная машина Ubuntu: 14.04, работает на хосте Windows, 64-битный Python 3.4.3, Python 2.7.6, 4 ядра, 4 ГБ ОЗУ
AWS: 14.04, микроэкземпляр AWS, 64-битный Python 3.4.3, Python 2.7.6
Нативная Ubuntu: 14.04, 64-битный Python 3.4.3, Python 2.7.6, i5-2500, 16 ГБ ОЗУ [идентично машине с Win10]

Обновить

По предложению Ингазаxrange а такжеbytes небольшое улучшение производительности, но все еще значительное падение производительности в Ubuntu с Python3.4. Виновным кажетсяfind что гораздо медленнее, когда объединяются Ubuntu и Py3.4 (то же самое с Py3.5, который был скомпилирован из исходного кода). Это, похоже, зависит от Linux, на Debian Py2.7 и Py3.4 выполнялись одинаково, на RedHat Py2.7 был значительно быстрее, чем на Py3.4.
Для лучшего сравнения Py3.4 теперь используется в 64-битной версии на Windows10 и Ubuntu. Py27 все еще используется на Win10.

import timeit, sys

if sys.version_info >= (3,0):
    from builtins import range as xrange

def sliding_window(text, word):
    for pos in range(0, len(text), 3):
        if text[pos:pos + 3] == word:
            return False
    return True

def xsliding_window(text, word):
    for pos in xrange(0, len(text), 3):
        if text[pos:pos + 3] == word:
            return False
    return True

def incremental_start(text, word):
    start = 0
    while start != -1:
        start = text.find(word, start + 1)
        if start % 3 == 0:
            return False
    return True

text = 'aaa' * 10**6
word = 'aaA'
byte_text = b'aaa' * 10**6
byte_word = b'aaA'

time = timeit.Timer(lambda: sliding_window(text, word), setup='from __main__ import text, word').timeit(number=10)
print('Sliding, regular:      %3.3f' % time)

time = timeit.Timer(lambda: incremental_start(text, word), setup='from __main__ import text, word').timeit(number=500)
print('Incremental, regular:  %3.3f' % time)

time = timeit.Timer(lambda: sliding_window(byte_text, byte_word), setup='from __main__ import byte_text, byte_word').timeit(number=10)
print('Sliding, byte string:  %3.3f' % time)

time = timeit.Timer(lambda: incremental_start(byte_text, byte_word), setup='from __main__ import byte_text, byte_word').timeit(number=500)
print('Incremental, bytes:    %3.3f' % time)

time = timeit.Timer(lambda: xsliding_window(byte_text, byte_word), setup='from __main__ import byte_text, byte_word').timeit(number=10)
print('Sliding, xrange&bytes: %3.3f' % time)

time = timeit.Timer(lambda: text.find(word), setup='from __main__ import text, word').timeit(number=1000)
print('simple find in string: %3.3f' % time)


Win10-py27  Wi10-py35   VM-py27  VM-py34
1.440       2.674       0.993    1.368 
1.864       1.425       1.436    5.711 
1.439       2.388       1.048    1.219 
1.887       1.405       1.429    5.750 
1.332       2.356       0.772    1.224 
3.756       2.811       2.818    11.361 

Ответы на вопрос(1)

Ваш ответ на вопрос