Говнокод - залог производительности

Курск
Существуют общепринятые правила хорошего тона при оформлении программного кода. Все их сформулировать довольно сложно, но давайте кратко остановимся хотя бы на следующих 3-х:
1. Осмысленные имена переменных.
2. Комментарии.
3. Избавление от повторяющегося кода.

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

Эксперименты будем ставить над ПэХэПэ — отличный пример интерпретируемого языка, распространенней некуда, к тому же никаких тебе байткодов.
Итак, начнем с конца — избавления от повторяющегося кода. Сразу вспоминаем про include, ну заодно и проверим его. Идея такова: введем переменную сумма, изначально равную 0, и в 6 циклах по 10 итераций будем увеличивать ее на 1. Смысла в этом нет никакого, зато получится очень наглядно. Создадим 6 следующих пхп-файлов, незабывая про умные названия переменных (надеюсь я не переборщил с этим):

Пусть это будет файл 1.пхп
<code><?php 
    $Thisimportantvariableisthesum=0;
    for($Thisimportantvariableisthecount1=1;$Thisimportantvariableisthecount1<=10;$Thisimportantvariableisthecount1++)
    {
        include "2.php";
    }
    echo $Thisimportantvariableisthesum;
?></code>
Это у нас файл 2.пхп и файлы 3-5 по анологии с ним
<code><?php 
    for($Thisimportantvariableisthecount2=1;$Thisimportantvariableisthecount2<=10;$Thisimportantvariableisthecount2++)
    {
        include "3.php";
    }
?></code>
И файл 6.пхп
<code><?php 
    for($Thisimportantvariableisthecount6=1;$Thisimportantvariableisthecount6<=10;$Thisimportantvariableisthecount6++)
    {
        $Thisimportantvariableisthesum=$Thisimportantvariableisthesum+1;
    }
?></code>
В итоге получаем 100 000 инклудов — неплохо, заодно создадим по аналогии серии файлов с 10 000, 1000, 100, 10 инклудами и еще один вообще без них, с той же последовательностью действий, и замерим время исполнения каждого случая.
Про измерение: для измерения скорости выполнения использовался скрипт на питоне, делающий серию измерений для каждого примера, находящий среднее время и среднее отклонение от него в процентах.
А вот и результаты (скорость выполнения скрипта в секундах в зависимости от количества инклудов):
<code>
0       - 0.079(с.) ±0.58%
10      - 0.083(с.) ±2.02%
100     - 0.087(с.) ±1.20%
1000    - 0.135(с.) ±1.82%
10 000  - 0.554(с.) ±1.10%
100 000 - 4.346(с.) ±0.16%</code>
Со 100 000 все-таки я наверное перебрал, скорее всего сказалась динамическая типизация, но тем не менее прогресс на лицо, точнее на часах. Да, 100 000 инклудов в реальном проекте быть не может, а вот 10 инклудов или даже 100, если проект более или менее сложный, вполне себе имеют право на жизнь.
С инклудами разобрались, перейдем к кометариям. За основу опять возьмем пример с 100 000 инклудами и сдобрим каждый его файл несколькими киллобайтами комментариев. Кстати я наконец то нашел применение твиттеру, копипаст ленты американского президента отлично подошел для этого. В каждый файл, примерный размер которого изначально был около 100 Байт, было добавлено почти 7 КБ бесполезной информации. Много? Действительно много, но это сделано для наглядности. Итак, запускаем скрипт и пролучаем результат:
7.060(с.) ±1.93%
Да уж, разница заметна, время выполнения увеличилась примерно в полтора раза.
Перейдем к осмысленным именам переменных. Из предыдущего примера уже должно быть понятно, что сокращение названий переменных ускорит выполнение скрипта, но мы все же поэксперементируем, заодно уберем лишние отступы, пробелы и переносы. За основу опять взят вариант с 100 000 инклудами из первого теста, каждый из его файлов уменьшен в размере примерно в 2 раза за счет сокращения названий переменных и удаления лишних символов. Посмотрим на результат:
4.167(с.) ±0.17%
Разница есть, но хотелось бы больше. Вспомним, что мы сократили размер файлов всего на 50 Б, в отличии от 7 КБ, как в предыдущем примере, но повторимся еще раз: разница есть.

Вот собственно и все, доказательств того, что все эти правила хорошего тона при оформлении кода, в конечном итоге, заставляют его работать медленее, придостаточно. Хотите поспорить с этим? — попробуйте!
А вывод простой: писать быстрый как молния говнокод или красивые, но медленные как черепаха скрипты, в конечном счете, выбирать Вам.

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

35 комментариев

  • аватар mihon
  • 0
Комментарии в коде — это дебаг. Дебага не должно быть в продакшене.
Тебе-то откуда знать?
  • аватар mihon
  • 0
Предчуствие
  • аватар ololo
  • 0
Это не дебаг, а документирование. Если есть уверенность, что после завершения работы над скриптом никто (даже автор) и никогда не будет вносить в него изменения, то правилом обязательного документирования кода можно пренебречь.
  • аватар mihon
  • +1
Я думаю, что большинство людей, пишущих серьезные проекты на php, итак пренебрегает многими правилами.
  • аватар ololo
  • 0
Не думаю, что программист, принципиально не комментирующий свой код сможет задержаться на сколько-нибудь значительный срок в компании, разрабатывающей что-то большее, чем сайты-визитки.
  • аватар mihon
  • 0
Сложный вопрос. Я php не особенно люблю. Если речь идет о документировании, то я предпочитаю документировать PRы.
И писать документацию к готовой смерженой фиче, а никак не в коде.
большинство людей, пишущих серьезные проекты на php, итак пренебрегает многими правилами
Например не писать серьезные проекты на php? :)
  • аватар ololo
  • +1
  • аватар SeL
  • +1
А каже тэги типа явадока? Или тэги ИДЕ?
  • аватар ololo
  • 0
В Яндексе, например, так не считают:
int TFlistDataSource::OpenIndexingSession(const char* config, const INDEX_CONFIG* ic)
{
    YxLogNotify = ic->YxLogNotify;
    LogObj = ic->LogObj;

    std::string docsfilepath("adddocs.txt");

    if (config && strncmp(config, "-p ", 3) == 0) {
        std::string config_str(config);
        size_t prefixEndPos = std::string::npos;
        size_t pos = config_str.find(" -d ", 4);
        if (pos != std::string::npos) {
            docsfilepath = config_str.substr(pos + 4);
            prefixEndPos = pos - 3;
        }
        prefix = config_str.substr(3, prefixEndPos);
    }
    // to do: считать конфигурацию из файла "config"

    remstream.open("remdocs.txt", std::ios::in);
    addstream.open(docsfilepath.c_str(), std::ios::in);
    if (remstream.is_open() || addstream.is_open(
        return YDS_OK;
    return YDS_EOF;
}

Это фрагмент кода бота-индексатора
  • аватар mihon
  • 0
Ну, это же не доки к коду. Хотя даже это — плохой знак. TODO должны быть отдельно, в менеджере проектов (basecamp, например) или в тасктрекере (trello, например). Зачем в продакшн такое вываливать?
  • аватар ololo
  • 0
Это я к тому, что в продакшене это никто никогда не увидит и никакого влияния этот комментарий на работающую программу не окажет.

А к коду есть обширные комментарии в начале каждого файла. Я не стал приводить целиком, поскольку у меня нет таких полномочий.
  • аватар mihon
  • +1
Немаловероятно, что у них так заведено. Если я прав, спорить не имеет смысла.
Это некий кодекс самих команд разработчиков или компаний. Это вопрос личных предпочтений, разумеется.
  • аватар dropp
  • 0
ИМХО:
1. Как сказал один чоткий пацанчик, код должен документировать сам себя. Не знаю, как там в ваших скриптолангуиджах принято, но вот мудаков, которые в сях на дефайнах экономят, хочется страпоном пиздить до крови.
2. Комментарии в коде — не дебаг. Это дань уважения себе будущему, мало ли в каком состоянии код писался, потом хрен вспомнишь, что имелось в виду. Вырезать или нет их из продакшена — личное дело каждого, опять же актуально лишь для скриптовых языков.
3. Дебагу в продакшене — быть. В меру, конечно, но сопровождение продукта очень облегчается наличием отладочных действий, которые может совершить пользователь под чутким руководством телефонной трубки. Нажать кнопочку и сосчитать, сколько раз моргнет лампочка на девайсе, если что-то пошло не так, сможет даже большинство оленей.
  • аватар mihon
  • 0
Для проверки работоспособности тесты есть. И уже давно.
  • аватар dropp
  • +1
Тесты всего не покрывают.
  • аватар ololo
  • 0
Вырезать или нет их из продакшена — личное дело каждого, опять же актуально лишь для скриптовых языков
а чем актуально-то?
  • аватар SeL
  • 0
Я тут слышал, что си не самый удачный пример — в нем исключения стемно обрабатываются до сих пор.
  • аватар ololo
  • 0
Красивые программы на php с комментариями и mvc (куча инклюдов) позволяют легко поддерживать и развивать код.

Предлагаю продолжить исследование и сравнить скорость исполнения скриптов с использованием любого из кэшеров байт-кода.
  • аватар SeL
  • 0
Про mvc и orm: имел я их возможность принимать один проект с ними. Тормоза ужасно жуткие. Нет, конечно с точки зрения оператора все ок — гламурно, красиво, но с точки зрения администратора, 8к записей одной из таблиц в БД удалялись более 2х!!! часов (ну или как это объяснить, там же другая организация данных). Системные требования на сервере были лучше чем рекомендовали разработчики.
  • аватар ololo
  • +1
Предположу, что если 8к записей удалялись в течение двух часов в рамках одного действия, инициированного оператором, то разработчики где-то крупно просчитались и orm тут, скорее всего, ни при чём.
  • аватар SeL
  • 0
Софт этот так и не приняли, но тем не менее, и причина была даже не в этом…
Но тем не менее к орм у меня остаются большие предъявы — он тормозной, реально. В каждой конкретной задаче БД можно очень неплохо оптимизировать под конкретные запросы, модель MVC это тоже касается, она хороша только для работы оператора, для администрирования — это тормоз.
  • аватар mihon
  • 0
«Мне кажется, вы не понимаете о чем поёте» — говорили в КВНе. О каком ormе идет речь? Тормознее чем что, чем голые sql-запросы? Разумеется. Но в голом sqlе нет ни грамма порядка. Я уже не говорю о всех плюшках и красоте кода, получаемого после применения orm (почти любого).
  • аватар SeL
  • 0
Объективно, он тормозной. Нужна скорость — нужно писать свой орм, под конкретную задачу. Я неоднактратно имел дело с эскуэльалкему. И не только с ним. Все эти орм реально снижают производительность, за счет абстрактности. СУБД используются реляционные, а не объктно-ориентированные, в этом и проблема. При желании могу замерить.
  • аватар mihon
  • 0
Вы меня неверно поняли. Я не спорю, что ORM медленней, чем просто sql. Я про то, что orm нужен в принципе.
  • аватар SeL
  • 0
Возможно и нужен, только вот его реализация, с моей точки зрения, должна от проекта к проекту очень сильно отличаться, в зависимости от задач. Да и к тому же уже есть СУБД, которые решили задачу объектно-ориентированного представления данных, кивок в сторону оракла.
  • аватар ololo
  • 0
Остаётся только оценить, что будет дороже в разработке и поддержке — продукт с оракловским стеком или с конкурирующей субд, orm и аппаратными мощностями, позволяющими свести недостатки orm к минимуму.

Нелишним также будет вспомнить, что реляционные субд можно достаточно успешно настраивать с целью повышения производительности, кроме того, в дополнение к ним можно использовать вспомогательные хранилища (например, key-value), если это позволяют условия задачи.
  • аватар SeL
  • 0
В том то и дело, что в конкретном случае в разработке дешевле взять готовую ИС и немного допилить, чем разработывать с нуля, и по времени это гораздо быстрее. Да и стоимость владения не такая большая за счет модели SaaS.
  • аватар SeL
  • 0
Небольшое уточнение. Сама по себе ИС возможно и использует подход orm, но за счет самой структуры БД. Но как бы тот функционал который от нее требуется не вызовет затыков в производительности, а вот та часть которую требуется запилить, там все куда сложнее — обработка больших объемов данных.
  • аватар ololo
  • 0
реализация орм в конкретном продукте тоже может хромать, поэтому с моей точки зрения не вполне корректно критиковать абстрактную технику вместо конкретного кода
  • аватар mihon
  • +1
Значит так было написано. Проект без использования orm для базы данных и без понимания mvc обречен со старта (вы понимаете, что я не про визитки, да?). Написать его, разумеется, напишут. Но как только дойдет дело до поддержки или, не дай Торвальдс, до оптимизации…
  • аватар SeL
  • 0
Сейчас есть один проект в разработке. Пару млн. записей в виде дерева. Применение SQLAlchemy себя не оправдало — тупит. Более хитрое предсталение данных в классической реляционной СУБД жрет диск, но себя оправлало, просто быстро. Ну а MVC…, а что сейчас не в базисе ООП? Правда есть свои методы работы с большим числом записей по шаблону, а не просто вызовы метода объекта в цикле. Очень вероятно предстоит миграция с PostgreSQL на продукты Oracle, там и посмотрим, что к чему, они рекурсивные запросы поддерживают.
  • аватар ololo
  • 0
Чем не устроил Постгрес и какие в контексте вашей задачи вы увидели преимущества у оракловсой СУБД по сравнению с первой?
  • аватар SeL
  • 0
Постгресс — промежуточный этап (в нем собираем текущие данные, точнее собираю), просто переходим на продукт, основанный на стеке технологий оракла.

Чтобы оставлять комментарии, нужно или зарегистрироваться.