Python/Оптимізація коду
Профілювання та оптимізація коду
[ред.]У стандартній бібліотеці Python є профайлер (модуль profile), який можна використовувати для збору статистики про час роботи окремих функцій. Для вирішення питання про те, який варіант коду працює швидше, можна використовувати модуль timeit
. Виміри, що проводяться в наступній програмі дозволяють з'ясувати, який з варіантів конкатенації рядків більш ефективний:
from timeit import Timer
def case1(): # А. інкрементального конкатенації в циклі
s = ""
for i in range(10000):
s += str(i)
def case2(): # Б. через проміжний список і метод join
s = []
for i in range(10000):
s.append(str(i))
s = "".join(s)
def case3(): # В. спискового вираз і метод join
return "".join([str(i) for i in range(10000)])
def case4(): # Г. генераторні вираз і метод join
return "".join(str(i) for i in range(10000))
for v in range(1,5):
print (Timer("func()","from __main__ import case%s as func" % v).timeit(200))
Як і в будь-якій мові програмування, у Python є свої прийоми оптимізації коду. Оптимізувати код можна, виходячи з різних (часто конкуруючих між собою) критеріїв (збільшення швидкодії, зменшення обсягу необхідної оперативної пам'яті, компактність вихідного коду і т. д.). Найчастіше програми оптимізують за часом виконання.
Тут є кілька очевидних правил:
- Не потрібно оптимізувати програму, якщо швидкість її виконання достатня.
- Використовуваний алгоритм має певну тимчасову складність, тому перед оптимізацією коду програми варто спочатку переглянути алгоритм.
- Варто використовувати готові і налагоджені функції та модулі, навіть якщо для цього потрібно небагато обробити дані. Наприклад, у Python є вбудована функція sort().
- Профілювання допоможе з'ясувати вузькі місця. Оптимізацію потрібно починати з них.
Python має такі особливості і пов'язані з ними правила оптимізації:
- Виклик функцій є досить дорогою операцією, тому всередині вкладених циклів потрібно прагнути уникати виконання функцій або, наприклад, переносити цикл у функції. Функція, обробна послідовність, ефективніша, ніж обробка тієї ж послідовності у циклі з викликом функції.
- Намагайтеся винести з глибоко вкладеного циклу все, що можна обчислити в зовнішніх циклах. Доступ до локальних змінних більш швидкий, ніж до глобальних, або ніж доступ до полів.
- Оптимізатор psyco може допомогти прискорити роботу модулю програми за умови, що модуль не використовує динамічних властивостей мови Python.
- У випадку, якщо модуль проводить масивну обробку даних і оптимізація алгоритму та коду не допомагає, можна переписати критичні ділянки, скажімо, на мові Сі або Cython.
Інструмент під назвою Pychecker[1] допоможе проаналізувати вихідний код на Python та видати рекомендації згідно зі знайденими проблемами (наприклад, невикористані імена, зміна сигнатури методу при його перевантаженні тощо). В ході такого статичного аналізу вихідного коду можуть бути виявлені і помилки. Pylint[2] покликаний вирішувати близькі завдання але більш схиляється до перевірки стилю коду.