Оптимизация программного кода. — it-black.ru
Оптимизация программного кода. — it-black.ru Перейти к содержимомуВ этой статье мы поговорим о старой традиции оптимизации кода. Но, сначала вспомним, что такое программный код:
Программный код — это написанный человеком текст компьютерной программы на каком-либо языке программирования.
Исходя из вышесказанного можно понять, что программный код может написать каждый программист или новичок, но правильно оптимизировать свой код намного сложнее. Давайте разберемся что же такое оптимизация.
Оптимизация кода — различные методы преобразования кода ради улучшения его характеристик и повышения эффективности. Среди целей оптимизации можно указать уменьшения объема кода, объема используемой программой оперативной памяти, ускорение работы программы, уменьшение количества операций ввода вывода.
Основные принципы оптимизации
- Естественность. Код должен быть аккуратным, модульным и легко читабельным. Каждый модуль должен естественно встраиваться в программу. Код должен легко поддаваться редактированию, интегрированию или удалению отдельных функций или возможности без необходимости вносить серьезные изменения в другие части программы.
- Производительность. В результате оптимизации вы должны получить прирост производительности программного продукта. Как правило, удачно оптимизированная программа увеличивает быстродействие минимум на 20-30% в сравнение с исходным вариантом.
- Время. Оптимизация и последующая отладка должны занимать небольшой период времени. Оптимальными считаются сроки, не превышающие 10 – 15 % времени, затраченного на написание самого программного продукта. Иначе это будет нерентабельно.
Начало оптимизации
Для начала необходимо выявить «узкие места» программы. В первую очередь, стоит обратить внимание на блоки кода, которые регулярно или часто повторяются в процессе работы – циклы и подпрограммы.
Участки кода, которые не оптимизируются
Не стоит трогать единичные операнды, поскольку работают они крайне редко и толку в их модификации нет никакого. Они отработают один раз, и больше к этому коду обращений не будет. Но при условии, что при внесении изменений вы добьетесь увеличения производительности более чем на 10%, это не лишено смысла.
Методы оптимизации программ
Оптимизация кода не слишком отличается от обычного исправления багов. Первым делом нужно проверить код на наличие устаревших или вообще ненужных фрагментов.
Пишите аккуратный код. Не забывайте о комментариях. Так вы поможете и себе, и другим разработчикам, понять, что в программе нужно, а что – уже не актуально. Эти общие советы помогают и при отладке, и при поиске багов.
Во вторых разберитесь, когда приложение работает медленнее всего, в какие моменты оно заметно подвисает. Изучите код на предмет ошибок или излишне сложных запутанных решений.
Вред и польза оптимизаций
Практически ко всему в программировании надо относиться рационально, и оптимизации — не исключение. Считается, что неопытный программист на ассемблере обычно пишет код, который в 3-5 раз медленнее, чем код, сгенерированный компилятором.
К оптимизациям, проводимым оптимизатором, у большинства нет претензий, причем иногда некоторые оптимизации являются практически стандартными и обязательными.
Следует понимать, что многочисленные сложные оптимизации на уровне машинного кода могут сильно замедлить процесс компиляции.
PVS-Studio
PVS-Studio — это инструмент для выявления ошибок и потенциальных уязвимостей в исходном коде программ, написанных на языках С, C++, C# и Java. Работает в среде Windows, Linux и macOS.
В статическом анализаторе PVS-Studio реализован набор диагностик, позволяющих обнаруживать некоторые ситуации, когда код может быть оптимизирован.
Анализатор PVS-Studio может выступать хорошим дополнением к инструментам профилирования. Более того, при работе с предупреждениями PVS-Studio, касающимися оптимизации, код часто становится проще и короче.
- Виктор Черемных
- 30 января, 2019
- No Comments
Группа в VK
Обнаружили опечатку?
Сообщите нам об этом, выделите текст с ошибкой и нажмите Ctrl+Enter, будем очень признательны!
Свежие статьи
Облако меток
Похожие статьи
Решение проблемы в оффлайн браузере Zeal — Content rendering error
В этом видео мы решаем проблему загрузки контента в оффлайн браузере Zeal.
Установка и обзор оффлайн браузера документации по программированию
В этом видео вы научитесь устанавливать оффлайн браузер Zeal для работы с документацией по программированию.
Зачем программисту изучать алгоритмы?
За всю историю компьютерных наук сложилось понимание, какие алгоритмы и структуры данных (способы их хранения) нужны для решения практических задач — так называемый джентльменский набор,
Что такое API?
API — это аббревиатура от английского Application Programming Interface, интерфейс программирования приложения. Говоря по-простому, API действует как виртуальный посредник и передает информацию из одного интерфейса,
Instagram Vk Youtube Telegram OdnoklassnikiПолезно знать
Рубрики
Авторы
Оптимизация программного кода | Techrocks
Зачем же нужна оптимизация и откуда она взялась? С первых дней развития эры вычислительной техники возник вопрос экономии места и увеличения производительности программ. Программистам приходилось создавать сложные дееспособные программы, которые смогли бы работать при очень низком быстродействии процессоров, использовать считанные килобайты оперативной памяти и места на диске. Поэтому все разработчики ПО были заинтересованы в максимальном быстродействии при минимальном размере кода.
Сегодня эти мощности вызывают улыбку. Но традиции оптимизации кода сохранились. Как известно, сколько ни наращивай размер диска и объем ОЗУ, все равно будет мало. Потому написанные «неряшливо» приложения, медленные и ресурсоемкие, проигрывают конкурентную борьбу аналогам, даже если они красивы и удобны.
Особо жесткие требования касаются драйверов и системных утилит. Они должны работать быстро, корректно и максимально экономить ресурсы компьютера. То есть взаимодействие процессора с периферией должно происходить без лишних затрат времени, с высокой скоростью передачи данных между устройствами. И сейчас мы решили немного разобраться, какие бывают способы оптимизировать программный код, в чем их плюсы и минусы.
Основные принципы оптимизацииОптимизация стоит на трех «китах» — естественность, производительность, затраченное время. Давайте разберемся подробнее, что они означают.
- Естественность. Код должен быть аккуратным, модульным и легко читабельным. Каждый модуль должен естественно встраиваться в программу. Код должен легко поддаваться редактированию, интегрированию или удалению отдельных функций или возможности без необходимости вносить серьезные изменения в другие части программы.
- Производительность. В результате оптимизации вы должны получить прирост производительности программного продукта. Как правило, удачно оптимизированная программа увеличивает быстродействие минимум на 20-30% в сравнение с исходным вариантом.
- Время. Оптимизация и последующая отладка должны занимать небольшой период времени. Оптимальными считаются сроки, не превышающие 10 – 15 % времени, затраченного на написание самого программного продукта. Иначе это будет нерентабельно.
Полезный совет. Перед началом оптимизации программного кода не забудьте сохранить копию исходного кода. Тогда в случае ошибки при внесении изменений всегда можно будет откатится до рабочей версии.
Стоит ли применять АссемблерМногие разработчики искренне считают, что критические секции (некоторые называют их «узкими» местами программы) кода удобнее писать на ассемблере, так как он обеспечивает самый быстрый доступ к данным и устройствам.
Многочисленные сравнения результатов оптимизации кода на языке высокого уровня и применения ассемблерных вставок показывают, что в первом случае после компиляции программа будет работать чуть медленнее, чем при использовании ассемблера. Обычно эти цифры измеряются от 2% до 7%. Максимум – разница составляет 20%. Стоит ли ради получения столь малого эффекта тратить время и силы на написание ассемблерной версии? На наш взгляд лучше уделить больше внимания работе с кодом, который написан на ЯП высокого уровня, и оптимизировать работу алгоритма.
Как правильно оптимизироватьТеперь давайте разберемся, как проводится оптимизация, и разберемся, с чего начинать, чего лучше избегать, и когда без ассемблера не обойтись.
Первое, что необходимо сделать, это выявить «узкие места» программы. Нет смысла трогать тот кусок программы, где и без вас все работает прекрасно. Здесь вы вряд ли что-то выиграете при оптимизации. В первую очередь, стоит обратить внимание на блоки кода, которые регулярно или часто повторяются в процессе работы – циклы и подпрограммы.
Пример: Если оптимизировать работу цикла хотя бы на 2% за одну итерацию, а число его повторов будет 1000 раз, в итоге мы получаем: 2% × 1000 = 2000%, вполне ощутимый результат при работе кода.
Участки кода, которые не оптимизируютсяНе стоит трогать единичные операнды, поскольку работают они крайне редко и толку в их модификации нет никакого. Они отработают один раз, и больше к этому коду обращений не будет. Но при условии, что при внесении изменений вы добьетесь увеличения производительности более чем на 10%, это не лишено смысла. Здесь все зависит от вашего здравого смысла и опыта.
Также вы не сумеете добиться достойных результатов в случае обращения к внешним устройствам и другим программным системам. До и после таких фрагментов можно что-то ускорить. Но там, где задержка может возникать по причине взаимодействия с внешними данными, лучше предусмотрите заглушку типа «Подождите, операция может занять несколько минут».
Еще раз об ассемблереПомните, что использовать ЯП низкого уровня нужно только там, где это действительно необходимо. Нет никакой причины вставлять его где ни попадя, это никак не повлияет на производительность. Впрочем, если вы – асс ассемблера и можете писать на нем также быстро, как и на удобном языке высокого уровня, можете пользоваться им активно. Правда, тогда возникает другой нюанс – вы усложняете читабельность кода для программистов, которые будут заниматься проектом после вас.
Оптимизировать или нет?Если вы не уверены, что сможете ускорить работу программы, при этом тестирование не выявляет никаких критичных проблем, оставьте все как есть. Помните старую мудрость программистов: работает – не мешай.
Иначе вы можете потратить лишнее время на работу с кодом, а в результате сделаете даже хуже, программа начнет работать медленно, да и от багов никто не застрахован.
Заниматься оптимизацией следует только тогда, когда на программу поступают жалобы пользователей либо на этапе тестирования находятся проблемные участки, на которых программа «подвисает» и тормозит работу устройства. В таких случаях производится отладка, а для уже выпущенных в серию продуктов выпускают новые версии или, так называемые, «заплатки» (patch).
Методы оптимизации программОптимизация кода не слишком отличается от обычного исправления багов. Более того, с их устранения и начинается работа по оптимизации программы.
Первым делом нужно проверить код на наличие устаревших или вообще ненужных фрагментов. Таких исполняемых модулей или веток в большой программе находится обычно много. Что-то написали, но оказалось, что функционал не нужен, и его просто забыли удалить. Другие части оказались не нужны в результате очередного обновления. Все они занимают место. А некоторые продолжают исполняться, хоть в этом нет никакого смысла. И, таким образом, замедляют работу системы.
Пишите аккуратный код. Не забывайте о комментариях. Так вы поможете и себе, и другим разработчикам, понять, что в программе нужно, а что – уже не актуально. Эти общие советы помогают и при отладке, и при поиске багов. В общем, не будьте неряшливым «говнокодером», и ваши программы будут работать быстро и без проблем.
Второй этап поиска проблемных мест также простой. Разберитесь, когда приложение работает медленнее всего, в какие моменты оно заметно подвисает. Изучите код на предмет ошибок или излишне сложных запутанных решений. Попробуйте написать проще.
Если все равно что-то не работает или «тормозит», придется использовать профилировщики отладочного вывода, в том числе, с учетом записи логов всех запросов SQL, если программа работает с базами данных. В случае поиска вслепую вы потратите много времени и не факт, что сможете добиться положительных результатов.
Рассмотрим самые популярные методы оптимизации программ. Некоторые из них возможно вызовут у вас недоумение, но поверьте, они работают.
Настройка окруженияИспользуемая вами SQL или другая система управления базами данных могут быть неверно настроены. Настройки по умолчанию далеко не идеальны. Возможно, какие-то дополнительные проверки как раз и замедляют процесс.
Иногда удается заметно ускорить работу программы, изменив ключевые настройки виртуальной машины Java. Кстати, это поможет сделать быстрее работу не только тестируемого приложения, но и всей системы.
Также обратите внимание на саму операционную систему и мощность «железа». Может быть они вообще не предназначены для работы программного продукта, который вы пытаетесь запустить и ускорить? А, может, устарели и потому «тормозят»?
Все это не относится напрямую к оптимизации программы, но проверить нужно до начала работы с кодом. Просто потому, что такие «досадные мелочи» нередко оказываются ключевой проблемой, а код – вообще не причем. И не стоит снисходительно улыбаться. Проверять окружение забывают даже опытные разработчики.
Избавляемся от ненужного функционалаДля увеличения скорости работы приложения можно использовать подход сокращения ненужного кода. Часто бывает так, что программа автоматически решает маловажные или уже не актуальные задачи. Например, заказчик, описывая задачу программисту, попросил о каких-то возможностях, а потом передумал. Или вышел новый релиз программы, где часть функций выделили в отдельный модуль, а старый код просто забыли удалить.
В итоге мы имеем лишний функционал, который будет «тормозить» быстродействие. Со временем такой код обрастет совершенно ненужными «костылями» и «подпорками», что не лучшим образом влияет на производительность. В таком случае мы рекомендуем просто переписать модуль «с нуля», выбросив все старое, как ненужных хлам.
МемоизацияМеморизация (от англ. Memoization) означает запоминание. Фактически это простое сохранение результата выполнения определенной функции, которое поможет избежать ее повторного выполнения. Применяя меморизацию, вы сможете повысить производительность программы.
Работает это очень просто. Перед тем, как функция будет выполняться, проверяется условие – исполнялась ли она ранее. По итогам можно получить два варианта:
- функция вызвана в первый раз, тогда она выполняется, а результат сохраняется;
- модуль уже работал, можно использовать сохраненный результат.
Иногда говорят о табулировании, это синоним мемоизации, который используется во многих языках программирования.
КешированиеЭто метод временного хранения данных в памяти устройства пользователя. Получить доступ к такой информации можно гораздо быстрее, чем каждый раз обращаться к серверу или базам данных. С помощью кэширования значительно ускоряют работу с сайтами, онлайн-системами и т.д.
Вся необходимая информация в данном случае храниться на носителях с быстрым доступом. Это может быть выделенная часть диска или оперативная память. Программа в процессе работы использует кэш по мере необходимости, и обращается к основному хранилищу данных только если не находит их в кэше.
Это способ адаптации алгоритмов, которые были реализованы, как программы для компьютерных систем с параллельной архитектурой. Как правило, это относится к многопроцессорным системам.
Подробно описывать метод мы здесь не будем, так как это займет слишком много места. Кратко можно сказать так: разные вычисления одной программы выполняются одновременно в параллельных потоках. Такой подход позволяют далеко не все языки, а потому тут нередко используют внешние команды системы или ассемблер.
«Ленивые» вычисленияЛенивые (Lazy evaluation) или отложенные вычисления – стратегия, которую применяют в некоторых системах счисления. Суть метода заключается в том, что все расчеты откладываются до тех пор, пока не будет затребован их результат.
Такая стратегия позволит существенно снизить общий объем производимых вычислений, так как ненужные операции попросту не будут выполняться. Чтобы метод начал работать, нужно описать зависимости функций (операндов) друг от друга, что поможет отслеживать работу. В итоге вы получите код, который будет выполняться только в том случае, когда он действительно нужен.
Метод приближенияПриближение или аппроксимаация (от лат. proxima — ближайшая или приближе́ние) – метод замены строгого алгоритма на наиболее подходящие приближенные значения, что влечет за собой определенную потерю точности вычислений. Снижение точности экономит память и повышает скорость. Для того чтобы не использовать длинную арифметику, можно воспользоваться обычными float’ами. Но пользоваться таким методом нужно крайне осторожно, не всегда снижение точности допустимо.
Использование сторонних языковИногда написанная программа может медленно работать из-за того, что много времени занимает проверка описанных типов, что занимает дополнительное время. Чтобы избежать этого эффекта, можно применять фрагменты кода или модули, написанные на других языках. Но делать это нужно крайне осторожно. Все эти «лишние» проверки защищают вас от багов и «дыр» в безопасности, связанных, в том числе, с буферизацией. Потому хорошо подумайте, действительно ли экономия времени столь существенна? И если придете к выводу, что здесь это – лучшее решение, обязательно проведите особо внимательное тестирование.
Кроме того, если начать использовать в коде фрагменты других языков, это может вызвать эффект «зоопарка», что сильно снижает читабельность программы. Также имейте в виду, что метод может попросту не сработать или даже критически навредить всей программе.
Существует еще очень много методов оптимизации, как общеизвестных, так и личных находок программистов. Мы постарались рассказать, что такое оптимизация, и познакомить вас с самыми популярными методами. А как вы ускоряете работу своих приложений? Делитесь в комментариях.
Лучший метод оптимизации кода Python — Stackify
Богдан Иванов Советы, хитрости и ресурсы для разработчиков
В настоящее время Python является наиболее используемым языком программирования для различных проектов по всему миру. По статистике, 44,1% программистов выбирают язык программирования Python для разработки приложений/веб-сайтов. Однако это не означает, что разработчики Python освобождаются от создания беспорядочного и неэффективного кода, который может стоить вам и вашим клиентам времени и денег. Именно здесь на помощь приходит оптимизация кода Python.0008
Что такое оптимизация?
Давайте начнем с определения оптимизации кода, чтобы вы получили основную идею и поняли, зачем она нужна. Иногда недостаточно создать код, который просто выполняет задачу. Большой и неэффективный код может замедлить работу приложения, привести к финансовым потерям для заказчика или потребовать больше времени для дальнейших доработок и отладки.
Оптимизация кода Python — это способ заставить вашу программу выполнять любую задачу более эффективно и быстро с использованием меньшего количества строк кода, меньшего объема памяти или других задействованных ресурсов, обеспечивая при этом правильные результаты.
Это важно, когда речь идет об обработке большого количества операций или данных при выполнении задачи. Таким образом, замена и оптимизация некоторых неэффективных блоков кода и функций может творить чудеса:
- Ускорить работу приложения;
- Сделать код чистым и читабельным;
- Упрощение отслеживания ошибок и отладки;
- Сэкономьте много вычислительной мощности и так далее.
6 лучших советов по оптимизации кода Python
Разработчики Python должны иметь возможность использовать методы оптимизации кода вместо базового программирования, чтобы обеспечить бесперебойную и быструю работу приложений. Ниже мы перечислили 6 советов о том, как оптимизировать код Python , чтобы сделать его чистым и эффективным.
1. Применение метода оптимизации Peephole
Чтобы лучше понять метод оптимизации Peephole, давайте начнем с того, как выполняется код Python. Изначально код записывается в стандартный файл, затем можно выполнить команду «python -m compileall
Результатом метода оптимизации Peephole является то, что Python предварительно вычисляет константные выражения 60*60*24, заменяя их на 86400. Таким образом, даже если вы все время пишете 60*60*24, это не снизит производительность.
Использование метода оптимизации Peephole
Используя этот метод, вы можете заменить раздел программы или сегмент инструкции без существенных изменений в выводе.
Применяя методику оптимизации, вы можете:
- Превращать изменяемые конструкции в неизменяемые. Это можно сделать, используя один из 3-х кортежей:
- <__code__.co_varnames>, в котором хранятся локальные переменные с включенными параметрами.
- <__code__.co_names>, который содержит глобальные литералы.
- <__code__.co_consts>, который ссылается на все константы.
- Проверьте принадлежность элемента, рассматривая инструкции как операцию с постоянной стоимостью, независимо от размера набора.
- Превратите набор и список в константы.
Обратите внимание на то, что это преобразование Python может выполнять только для литералов. Таким образом, оптимизация не произойдет, если какой-либо из используемых наборов или списков не является литералом.
Давайте рассмотрим несколько примеров:
- «Привет, мир!» * 5 — константное выражение длиной менее 4096. Поэтому компилятор оценивает его как «Hello, world!» 5 раз подряд
- [1, 2] * 7 — это список (изменяемый объект), поэтому он не оценивается.
- (10, 20, 30) * 3 — это последовательность длины 9, которая меньше 256 (для кортежей), поэтому она хранится как (10, 20, 30, 10, 20, 30, 10, 20, 30) .
2. Внутренние строки для повышения эффективности
Строковые объекты в Python представляют собой последовательности символов Unicode, поэтому в документации они называются «текстовыми» последовательностями. Когда в строку добавляются символы разного размера, ее общий размер и вес увеличиваются, а не только на размер добавленного символа. Python также выделяет дополнительную информацию для хранения строк, из-за чего они занимают слишком много места. Для повышения эффективности используется метод оптимизации, называемый интернированием строк.
Идея интернирования строк заключается в кэшировании определенных строк в памяти по мере их создания. Это означает, что в любой момент времени активен только один экземпляр конкретной строки, и для обращения к нему не требуется новая память.
Интернирование строк имеет много общего с разделяемыми объектами. Когда строка интернируется, она рассматривается как общий объект, потому что экземпляр этого строкового объекта глобально используется всеми программами, работающими в данном сеансе Python.
Будучи наиболее распространенной реализацией языка программирования Python, CPython загружает общие объекты в память каждый раз при инициализации интерактивного сеанса Python.
Вот почему интернирование строк позволяет Python работать эффективно с точки зрения экономии времени и памяти.
Строки идентификаторов
Python имеет тенденцию хранить только те строки, которые с наибольшей вероятностью будут использоваться повторно, а именно строки идентификаторов:
- Имена атрибутов;
- Имена переменных;
- Имена аргументов;
- Имена функций и классов;
- Ключи словаря.
Принципы интернирования строки:
- Только строка, загруженная во время компиляции как константная строка, будет интернирована, и наоборот, строка, созданная во время выполнения, не будет интернирована.
- Строка не будет интернирована, если она является результатом свертки констант и имеет длину более 20 символов, потому что вряд ли она является идентификатором.
- Python будет интернировать строку и создавать для нее хэш, только если он объявляет строку с именем, которое включает только комбинации букв/цифр/черных символов и начинается либо с буквы, либо с символа подчеркивания.
Таким образом, все строки, прочитанные из файла или полученные по сети, не являются частью о-интернирования. Однако просто перенесите такую задачу в функцию intern() , чтобы начать интернирование таких строк и их обработку.
3. Профилируйте свой код
Профилируя свой код, вы можете определить области улучшения в вашем коде для дальнейшей оптимизации. Есть два основных способа сделать это.
1. Используйте Используйте профилирование секундомера с этим модулем.
Вот как это вычисляется:
2. ИспользуйтеЭто расширенное профилирование, которое является частью пакета Python, начиная с Python 2.5. Есть несколько способов связать его с кодом Python:
- Обернуть функцию внутри ее метода запуска и таким образом измерить производительность;
- Запустите весь сценарий из командной строки, активировав cProfile в качестве аргумента, используя параметр Python «-m».
Зная ключевые элементы отчета cProfile, вы сможете найти узкие места в своем коде.
Вот элементы, которые следует учитывать:
-
— количество совершенных звонков; -
— совокупное время, проведенное в данной функции и имеющее наибольшее значение; -
— отношение к ; -
— еще один очень важный для всех проектов параметр, который представляет собой совокупное время выполнения функций, их подфункций; -
— частное от деления на примитивные вызовы;
4. Используйте генераторы и ключи для сортировки
Это способ оптимизировать память с помощью такого замечательного инструмента, как генераторы. Их особенность в том, что они не возвращают сразу все элементы (итераторы), а могут возвращать только по одному. При сортировке элементов в списке лучше использовать ключи и метод по умолчанию
Как это может выглядеть:
5. Не забывайте о встроенных операторах и внешних библиотеках
В Python доступны тысячи встроенных операторов и библиотек. Лучше использовать встроенные модули везде, где это возможно, чтобы сделать ваш код более эффективным. Это возможно благодаря тому, что все встроенные модули предварительно скомпилированы и, таким образом, работают довольно быстро.
Эквивалент «C» некоторых библиотек Python предоставляет вам те же функции, что и исходная библиотека, но с более высокой производительностью. Итак, попробуйте использовать, например, cPickle вместо Pickle, чтобы увидеть разницу. Пакет PyPy и
6. Избегайте использования глобальных переменных
Глобальные переменные могут иметь неочевидные и скрытые побочные эффекты, приводящие к спагетти-коду. Более того, Python медленно обращается к внешним переменным. При этом от их использования лучше отказаться или хотя бы ограничить их использование. Если они необходимы, вот несколько рекомендаций:
- Используйте ключевое слово global для объявления внешней переменной;
- Сделайте локальную копию, прежде чем использовать их внутри циклов.
Нижняя строка
Крайне важно создать надежное и масштабируемое приложение, которое выполняет задачи быстро и плавно. Однако разработать такое приложение, используя только базовые методы кодирования, невозможно. Вот почему вам нужно оптимизировать код Python. В то же время, используя методы оптимизации, описанные в статье, вы сможете не только создать чистый код, но и повысить производительность приложения, сэкономив массу времени и денег.
Богдан Иванов — технический директор DDI development. Он профессионал с высшим образованием в области кибербезопасности и 7-летним опытом построения стратегии кибербезопасности для всех проектов компании. Он глубоко разбирается в сетевой безопасности, соблюдении нормативных требований и операционной безопасности.
- Об авторе
- Последние сообщения
О Богдане Иванове
Богдан Иванов является техническим директором в DDI Development. Он профессионал с высшим образованием в области кибербезопасности и 7-летним опытом построения стратегии кибербезопасности для всех проектов компании. Он глубоко разбирается в сетевой безопасности, соблюдении нормативных требований и операционной безопасности.- Как оптимизировать код Python — 21 июля 2021 г.
Оптимизация кода Python. Важные советы по работе с большими… | Анна Астори
Важные советы по работе с большими объемами данных в Python это определенно хорошая идея, чтобы выработать привычку писать эффективный код и сразу же определять места, где вы можете его улучшить.
При поиске способов оптимизации кода важно помнить, что, скорее всего, всегда придется идти на некоторые компромиссы. Например, это либо более быстрый фрагмент кода, либо более простой. И простота здесь не означает просто «код, который выглядит менее круто» (вспомните знаменитые «однострочники» Python). Более простой код означает, что его будет легче поддерживать и тестировать.
Кроме того, каждый совет по оптимизации вашего кода Python должен быть критически изучен в вашем случае. Есть, конечно, общие наблюдения, но у вас также может быть контекст, в котором эти наблюдения неуместны или даже приводят к противоположному результату. Поэтому вам нужно понимать, что происходит «за кулисами» и как это будет работать в вашем случае.
Однако бывают ситуации, когда вам определенно нужно немного улучшить свой код, и вот некоторые моменты, которые я нашел полезными, когда изучал Python.
1. Включение списков
В Python отличная синтаксическая конструкция, которая в вычислительном отношении более эффективна для создания списков, чем традиционный цикл, — это включение списков. Итак, если вам нужно, скажем, иметь двоичный вектор признаков для списка чисел в качестве точек данных, где всем отрицательным числам будет присвоен 0, а остальным будет присвоен 1, вместо:
>>> input_list = [1, 2, -3]
>>> output_list = []>>> для x в input_list:
... если x >= 0:... output_list.append(1)... else:... output_list. добавить(0)>>> output_list[1, 1, 0]
Вы можете сделать:
>>> output_list = [1 if x >= 0 else 0 for x in input_list]>>> output_list[1, 1, 0]
Вы можете попробовать и сравнить, какая реализация работает быстрее, используя , например, модуль timeit
.
У вас также могут быть вложенные списки, как и вложенные циклы, но обычно это не рекомендуется именно потому, что код становится труднее читать, поддерживать и тестировать.
2. Избегайте циклов for и списков, где это возможно
На самом деле, в предыдущем примере, если бы вы создавали вектор только с одним значением инициализации, вместо использования неэффективных циклов for и даже включения списков вы могли бы сделать что-то вроде этого:
>>> my_list2 = [0 ] * len(my_list1)
>>> my_list2
[0, 0, 0]
3. Избегайте ненужных функций
Хороший пример подхода, который может помочь значительно снизить сложность выполнения, но требует много тщательного рассмотрения с точки зрения компромиссов являются вызовы функций. Хотя вам нужны хорошая абстракция, расширяемость и возможность повторного использования, которые обеспечивают функции, вы, возможно, не захотите иметь функцию для каждой отдельной вещи, потому что вызовы функций довольно дороги в Python (если вам интересно, есть интересные наблюдения об этом в этой статье). Поэтому иногда вы можете захотеть пожертвовать, например, написанием геттера и/или сеттера. С другой стороны, меньшее количество функций делает код менее пригодным для тестирования. Так что окончательное решение действительно зависит от специфики вашего приложения.
4. По возможности используйте встроенные функции
Еще один совет, связанный с функциями, заключается в выборе встроенных функций, таких как max()
, sum()
, map()
, reduce()
и т. д. , а не выполнять эти вычисления самостоятельно — они обычно написаны на C и будут выполняться быстрее. Также, если вы используете встроенную функцию — это меньше кода, вам придется писать тесты для себя. Так, например, если вам нужен набор, состоящий из всех абсолютных значений input_list
, вы можете сделать что-то вроде этого:
>>> output_set = set(map(abs, input_list))
>>> output_set
{1, 2, 3}
Если вы работаете с текстовыми данными, для конкатенация строк вместо +=
:
>>> приговор_список = ['Это', 'есть', 'а', 'предложение. ']
>>> предложение = ''
>>> для я в предложение_список:
... предложение += i
>>> предложение
'Это предложение.'
используйте str.join()
:
>>> предложение = ''.join(sentence_list)
>>> предложение
'Это предложение.'
С +=
Python выделяет память для каждой промежуточной строки и только один раз, если используется str.join()
.
Используйте operator.itemgetter
для сортировки. Если у вас есть список кортежей, например, имен и фамилий, например:
>>> my_tuples =[('abbie', 'smith'), ('jane', 'adams'), ('adam ', 'Джонсон')]
Сортировка по умолчанию вернула бы это:
>>> sorted(my_tuples)
[('абби', 'кузнец'), ('адам', 'джонсон'), ('джейн', 'адамс')]
Если вы хотите, чтобы он сортировался по фамилиям, а не по именам, вы можете сделать это так:
>>> sorted(my_tuples, key=operator.itemgetter(1))
[('jane', ' adams'), ('adam', 'johnson'), ('abbie', 'smith')]
5.
Избегайте точкиЕсли у вас есть объект и вы используете некоторые его свойства, назначьте их сначала локальные переменные:
прямоугольник_высота = прямоугольник.высотапрямоугольник_ширина = прямоугольник.ширина
Итак, если позже в своем коде вы вычисляете, например, его поверхность, вы будете делать:
поверхность = прямоугольник_высота * прямоугольник_ширина
периметру вы будете повторно использовать одни и те же переменные:
периметр = 2 * прямоугольник_высота + 2 * прямоугольник_ширина
Вы можете снова использовать модуль timeit
, чтобы убедиться, что он экономит время поиска для каждой ссылки на объект прямоугольника и его свойства.
По тем же причинам использование глобальных переменных часто не рекомендуется — вы не хотите тратить время на поиск сначала самой глобальной переменной, а затем каждого из ее свойств, на которые вы можете ссылаться.
Это также может относиться к ссылкам на функции. Если вы обрабатываете, например, последовательность точек данных и добавляете каждый полученный элемент в список, вы можете сделать следующее:
push_item = my_list.append
, а затем применить это к каждому полученному элементу:
push_item(item)
6. Знайте свои структуры данных и знайте, как они работают в вашей версии Python
В дополнение к общим свойствам каждой типовой структуры данных, например, сложности извлечения элемента из связанного списка , полезно знать, как реализованы структуры данных Python и где вы можете сэкономить процессор или память. Например, если вы ищете ключ в словаре, вам даже не нужно ссылаться на dict.keys()
, что делает его немного медленнее в Python 3. Вы можете просто сделать:
>>> if k in dict:... do_something(k)
В Python 2 dict.keys()
даже используется для создания дополнительного списка ключей!
7. Выбирайте подход с умом
В то же время не забывайте смотреть на картину шире.
Если у вас есть список элементов для обработки, и вы знаете, что поиск в наборе — это O(1) против O(n) в списке, у вас может возникнуть соблазн превратить ваш список в набор:>>> my_set = set(my_list)
Однако, если вы ищете только один элемент этого списка, вы можете усугубить ситуацию, если сначала превратите свой список в набор. За кулисами Python будет перебирать весь ваш список и добавлять каждый элемент во вновь созданный набор. Накладные расходы на создание набора заставят вас потерять преимущество поиска в наборе.
С другой стороны, если вы хотите эффективно удалить дубликаты из списка, приведение его к set может быть хорошим вариантом (хотя в Python есть и другие варианты для этого, которые могут лучше подойти для вашего случая).
Итак, как я упоминал ранее, есть общие наблюдения, но вам нужно внимательно их изучить, чтобы понять, как они будут работать в вашем случае.
Существует множество более продвинутых подходов к управлению вашим кодом, чтобы сделать его более эффективным и быстрее выполняться — от параллелизма или параллелизма до различных трюков, таких как проектирование объектов меньшего размера, чтобы они помещались в кэш-уровень кучи памяти, а не чем основной.