Оптимизация

Оптимизация

> Учебник LeekScript

Здесь мы поговорим об оптимизации, цель оптимизации — повысить производительность алгоритма. В общем, когда мы говорим об оптимизации, мы говорим о времени выполнения, целью которого является сокращение времени, необходимого для выполнения серии инструкций.

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

Если вы еще этого не сделали, я приглашаю вас прочитать статью LeekScript Tutorial: Operations.

Хорошие рефлексы

Например, сохранение 500 операций для функции, вызванной только один раз, сохранит только 500 операций. (логика) С другой стороны, экономия одной операции над функцией, которая вызывается в цикле из цикла в цикле, может снизить стоимость операций в несколько десятков тысяч операций.

Что подводит меня ко второму пункту:

Половина работы по оптимизации кода состоит просто в том, чтобы искать, куда уходят операции (потом приходится громко кричать и приказывать им вернуться). Что дорогого в коде?

Для этого, не секрет, мы будем мерить!

В нашем арсенале LeekScript предоставляет очень полезную функцию: getOperations. Эта функция позволяет узнать количество операций, проведенных до сих пор в коде.

Пример простого инструмента для измерения стоимости функции:

глобальная __debug_operation; функция startOp(){ __debug_operation = getOperations(); } функция stopOp(название){ let ops = getOperations()-__debug_operation - 3; debug("Операции (" + title + "): " + ops); }

стартОп(); stopOp("пустой тест"); // пустой тест: 0

стартОп(); сказать("привет мир"); стопОп("привет мир"); // привет мир: 30

Таким образом, мы можем подтвердить, что say стоит 30 операций, как заявлено в документации.

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

Страница Сложность поможет вам понять, почему алгоритм стоит дорого и как решить проблему. Подводя итог очень просто, мы предпочитаем избегать вложенных циклов между ними, насколько это возможно. Мы также будем стремиться ограничить размер наших циклов, например, просматривая только наши доступные ячейки, а не просматривая все ячейки карты. Важно отметить, что алгоритм с более низкой сложностью будет использовать намного меньше операций для обработки достаточно большого количества элементов, подумайте об этом, прежде чем пытаться поцарапать небольшие оптимизации!

Удаление циклов, которые не изменятся

Представьте себе следующий код:

пусть ТП = получить ТП();

// стреляем во врага как можно больше раз! for (var i = 0; i < floor(TP / getWeaponCost(getWeapon())); i++) { использовать оружие (getNearestEnemy ()); }

Функция getNearestEnemy будет вызываться на каждой итерации цикла, при этом она всегда будет возвращать один и тот же результат! Чтобы этого избежать, просто поместите результат в переменную перед функцией. Мы делаем то же самое для floor(TP / getWeaponCost(getWeapon())), который также оценивается на каждой итерации. Которые дают:

пусть ТП = получить ТП();

// стреляем во врага как можно больше раз! вар враг = getNearestEnemy(); var nbShots = floor(TP / getWeaponCost(getWeapon())); // количество возможных выстрелов из текущего оружия for (var i = 0; i < nbShots; i++) { использовать оружие (враг); }

Дорогостоящие функции Leek Wars

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

функция inArray (элемент, массив) { for (значение var в массиве) если (значение == элемент) вернуть истину; вернуть ложь; }

Этот пример является хорошей иллюстрацией, чтобы говорить о некоторой сложности. Здесь мы видим, что реальная стоимость этой функции зависит в худшем случае от размера массива массива, который мы назовем n*. Таким образом, эта функция имеет сложность *n, она