В моем приложении Python GAE следующий фрагмент кода МНОГО медленнее в производстве, чем при локальном запуске. Обработка выполняется следующим образом:GAE Python код МНОГО медленнее в производстве, чем локально
- В POST загружается текстовый файл объемом около 1 МБ. Каждая строка текстового файла является «элементом».
- Мой код создает список элементов из текстового файла и проверяет наличие дубликатов и достоверность (путем сравнения с скомпилированным RE).
Вот код:
def process_items(self, text):
item_list = text.split()
item_set = set()
n_valid = 0
n_invalid = 0
n_dups = 0
out = ""
for item in item_list:
if item in item_set:
n_dups += 1
out += "DUPLICATE: %s\n" % item
elif valid_item(item): # This compares against a compiled RE
item_set.add(item)
n_valid += 1
out += "%s\n" % item
else:
n_invalid += 1
out += "INVALID: %s\n" % item
return out
Когда я запускаю это на локальном сервере Dev, 1Мб файл 50000 строк занимает 5 секунд, чтобы обработать.
Когда я запускаю это в процессе производства, тот же файл занимает минуту, а запрос истекает. Загрузка файла занимает всего около секунды, поэтому я знаю, что шея бутылки - это код выше.
В прошлом производственный код был примерно такой же, как у моего локального кода. Я не думаю, что этот код изменился, поэтому я подозреваю, что в конце Google произошли изменения.
Любая идея, почему этот код сейчас намного медленнее в производстве? Что-нибудь, что я могу сделать, чтобы сделать этот код быстрее? Мне нужно вернуть аннотированный файл пользователю, который указывает, какие строки являются дубликатами и какие строки недействительны.
EDIT:
В ответ на комментарий mgilson, я попытался следующий код, и он сделал огромную разницу во времени исполнения! Обработка, которая ранее была отключена через минуту, занимает всего около 5 секунд. GAE все еще медленнее, чем ожидалось (даже учитывая относительно медленные серверные процессоры), но с улучшенным алгоритмом для меня это не имеет значения.
def process_items(self, text):
item_list = text.split()
item_set = set()
n_valid = 0
n_invalid = 0
n_dups = 0
for i, item in enumerate(item_list):
item = item.strip()
if item in item_set:
n_dups += 1
item_list[i] = "DUPLICATE: %s" % item
elif valid_item(item): # This compares against a compiled RE
item_set.add(item)
n_valid += 1
item_list[i] = item
else:
n_invalid += 1
item_list[i] = "INVALID: %s" % item
return "\n".join(item_list)
Сравнивая локальный ход и работает на GAE не очень справедливо. В зависимости от вашего набора [класс экземпляра] (https://cloud.google.com/appengine/docs/about-the-standard-environment#instance_classes) у вас может быть предел процессора до 600 МГц. Большинство персональных компьютеров _significantly_ быстрее, чем сейчас. Одна сразу очевидная оптимизация, что _might_ help заключается в том, чтобы накапливать результаты в списке и «возвращать» «.join (results)» в конце, а не использовать '+ ='. См. [Почему «.join() быстрее, чем + = в Python?] (Http://stackoverflow.com/q/39312099/748858), например ... – mgilson
Создание' process_items' генератора 'yielding' одной строки в то же время ускорит его общее время обработки, устраняя медленный '+ =' –
@mgilson, My Mac - 2,2 ГГц, поэтому он в 3,7 раза быстрее, чем GAE. Для этого кода на Python мой Mac по крайней мере на 12 раз быстрее, чем GAE. Это все еще кажется большим несоответствием, хотя я понимаю, что многие факторы делают его несовершенным сравнением. –