PHP создан, чтобы умирать

http://software-gunslinger.tumblr.com/post/47131406821/php-is-meant-to-die
  • Перевод
Дисклеймер: у меня за спиной более десяти лет разработки на PHP. Я начал использовать его, когда PHP4 был совсем малышом, а PHP5 — только мечтой компании Zend. С помощью него я сделал многое, я любил его, проклинал и не без стыда наблюдал за тем, как он растёт и развивается. Я всё ещё использую его в некоторых доставшихся по наследству проектах, но предпочитаю больше его не применять. Также хочу отметить, что я не сотрудничаю с создателями фреймворков или инструментов, упомянутых в статье.

TL;DR (англ. too long; didn't read. Так, в частности, говорят, когда лень читать статью целиком — прим. пер.): если ваш проект основан на функциях фоновых процессов (фоновых служб, демонов — прим. пер.), избегайте PHP.

По-моему, в большинстве случаев ненавистники PHP упускают один весьма важный момент: PHP создан, чтобы умирать. Это не значит, что довольно способный (в какой-то степени) язык программирования исчезнет в никуда; это всего лишь означает, что ваш PHP код не может выполняться вечно. В настоящее время, спустя 13 лет после первого официального релиза в 2000 году, эта мысль до сих пор кажется мне вполне обоснованной.

Модель умирающей программы


Ядро PHP следует самому простому рабочему процессу: получить введенные данные, обработать их, отобразить вывод и умереть. Думаю, сайты вроде PHP Sadness, которые весело и непринужденно помогают выявить несостоятельность языка, лучше всех могут повлиять на его архитектуру в целом. Но, наверняка, были и другие попытки.

В самом начале завершение процесса (англ. dying) не было большой заботой веб-сайтов. Вы считывали что-нибудь из базы данных, применяли логику или форматировали данные и выводили результат среди моря HTML тэгов. PHP до сих пор трудно в этом превзойти (это особенность его ядра), несмотря на весь ужас, привнесенный таким подходом в мир программирования. Хорошо, что все проблемы, которые можно было решить таким способом, уже решены, а оставшиеся решаются более умными и современными инструментами, потому что такая крошечная функциональность — это обычно малая часть в составе большого, сложного проекта. Увы, PHP настаивает на смерти после выполнения. А когда вы пытаетесь сделать наоборот, случаются плохие вещи.

Уже не просто веб-сайт


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

Давайте пропустим этот момент. Теперь мы пишем реальное и сложное приложение. Одновременно со сложностью растет количество программного кода. Допустим, что вы довольно способный программист. Вы используете PHP 5.x и современные программные методы. Все предельно абстрактно в интерфейсах и классах. Вы знаете, что делать с существующими библиотеками. Теперь вы, возможно, зависите от ваших собственных ORM-моделей, кода сторонних разработчиков, разработанного интерфейса, возможно, ваших клиентских API-функций для сторонних REST-интерфейсов и т.д. Всё написано на PHP.

Тут-то и начинается кошмар: вам неизбежно придётся запускать код в фоновом режиме. Ваше приложение достигло уровня сложности, при котором ожидания выполнения HTTP-запроса не достаточно. Причины могут быть следующие: вам нужно обрабатывать очереди запросов или кэшировать информацию для ускорения HTTP-ответов; вам периодически нужно проверять обязательные платежи и действовать в зависимости от результата или постоянно обновлять данные, получаемые из внешних источников; вам также может понадобиться запись в базу данных целых пакетов данных, чтобы избежать потери производительности; может понадобиться создавать и оставлять открытыми несколько сетевых соединений или выполнять работу серверной части WebSocket-приложения. Это только примеры и их можно перечислять бесконечно, в зависимости от того, что вы разрабатываете.

Вызывайте в интерактивном режиме


Самая плохая реализация вещей, описанных выше, может, однако, показаться довольно знакомой: не важно, чего требует PHP или выбранный фреймворк — наверняка, на вашем хостинге за 5 долларов в месяц нет доступа по SSH, утилиты cron или похожего инструмента.

Какое же из решений самое простое? Конечно, перенести выполнение заданий из фонового режима в интерактивный! Запускайте их случайно через каждое n-ное посещение страницы (for 1/nth of page visits — ориг.). Тогда случайный посетитель будет тратить свое время на ожидание выполнения общесистемной фоновой задачи, и только после ее завершения личный запрос пользователя будет обработан. Становится тревожно при мысли о том, что во многие «серьезные» и «развитые» фреймворки изначально встроена такая функция, потому что довольно сложно не только найти участки кода, отвечающие за этот процесс, но и разбираться в их переплетениях.

Так в чем же беда? Во-первых, нет необходимости в специальных параметрах доступа к серверу; вполне достаточно старого, доброго и бесхитростного FTP. Во-вторых, все срабатывает по запросу клиента, и небольшая задержка для него незаметна. Именно поэтому провал обеспечен: все работает замечательно во время тестирования, также хорошо на этапе внедрения, но некрасиво под реальной нагрузкой. Вы самонадеянно думаете, что посещений будет примерно столько, сколько вам нужно для запуска задач с интервалом в несколько минут. Но псевдослучайность на выборке из n-сотен нельзя сопоставлять с тысячами запросов в минуту. Задачи, которые должны запускаться через определенное время, на деле обрабатываются несколько раз в мгновение ока. Начинают происходить забавные вещи: например, одна и та же задача запускается и завершается в одно и то же время, появляются ошибки, когда несколько процессов пытаются получить доступ к общим ресурсам с механизмом блокировки и т.д. Имейте в виду, что аварийное завершение процессов также приводит к невозможности загрузки запрашиваемой страницы, потому что, как вы знаете, PHP умирает, а вслед за ним всё остальное, включая запрос пользователя. В данном случае смерть — не гарант успеха.

Если вы довольно предприимчивы, то можете переместить фоновые процессы в список задач обработчика cron. Так уже лучше: это работает пока хватает времени, т.к. в данном случае у нас всего одна переменная управления. В случае рекурсивных задач (рекурсия здесь — это сущность ядра демона crond) вы всегда предполагаете, что одна задача завершится до того, как она же вызовется снова. В большинстве случаев это может оказаться так, но, с другой стороны, вам, возможно, придется корректировать интервалы планировщика, если нагрузка на сервер будет возрастать, или надеяться на достаточно долгое выполнение одного из них, что может быть безопасно, но губительно для скорости вашего приложения. В масштабах системы этот метод может оказаться очень и очень сложным. К этому времени вы уже можете задуматься о разбиении общесистемных задач на отдельные пакеты. Но кто-то должен за этим следить, кто-то, кто не умрет.

Призовите демонов


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

Но PHP подведёт вас.

Есть несколько задач, для выполнения которых PHP не годится. Помните, что PHP умирает, как бы вы не старались этому помешать. Во-первых, это проблема с утечкой памяти. PHP никогда не заботится о её освобождении, в случае если она больше не используется, потому что все освободится в конце — после смерти. В непрерывно выполняемых процессах выделяемая память (которая, фактически, пустует) будет накапливаться до достижения порогового значения memory_limit. После этого ваш процесс будет завершен без предупреждения. Проблема тут не в вас, если только вы не ожидали, что процесс будет жить вечно. При реальной нагрузке замените «медленные» процессы на "довольно быстрые".

Конечно, были улучшения в плане «не тратьте память впустую», но их оказалось не достаточно. Как только сложность возрастает или растет нагрузка, все ломается. Рассмотрим следующий фрагмент кода:

class FOO {
    public $f;
}

class BAR {
    public $f;
}

while(1) {
    $a = new FOO();
    $b = new BAR();
    $a->f = $b;
    $b->f = $a;
    print "Memory usage: " . number_format(memory_get_usage(true)) . " bytes\n";
    unset($a);
    unset($b);
}

Здесь представлены так называемые циклические ссылки, объекты, ссылающиеся на другой объект, который в свою очередь ссылается на первоначальный. Когда вы запустите этот скрипт, в зависимости от версии PHP он будет медленно потреблять все больше и больше памяти, потому что во время выполнения проверка на то, что все циклические ссылки больше не используются, выполняться не будет, даже если вы явно попытаетесь освободить их командой unset().

Это довольно распространённый пример. Вы можете найти еще примеры того, что происходит, когда программа становится более сложной, чем в приведённом выше скрипте. Можно поспорить о том, хорошо или плохо использовать циклические ссылки, но есть одно место, где они встречаются в изобилии: ORM. По некоторым уважительным причинам объект, представляющий запись в базе данных, это один и тот же объект в памяти и он ссылается на все другие объекты, если это необходимо, основываясь на ограничениях внешних ключей. Это позволяет избежать многих проблем, таких как каскадное обновление записей через ссылки связанных моделей. А теперь взгляните на схему своей базы данных и посчитайте, сколько у вас внешних ключей… взгляните, сколько циклических ссылок у вас может быть в запущенных процессах? PHP не сможет подсказать, какие из них используются, а какие нет, но рано или поздно свободная память исчерпается, будучи используемая или нет, и PHP умрет.

Важнее того факта, что поддержание работоспособности программы никогда не было приоритетной задачей для PHP, является вопрос: почему подобные проблемы (одна из которых описана выше) никогда серьезно не решались. Механизм сбора мусора (Garbage collection — ориг.) впервые был представлен в PHP 5.3 как подключаемая функция. Всё верно: язык спрашивает вас «пожалуйста, не могли бы вы предотвратить утечку памяти?». Это была середина 2009 года, относительно недавние изменения. Что же происходило до этого? Абсолютно ничего. Никому не было дела до того, предотвращает ли PHP утечку памяти или нет, потому что он создан, чтобы умирать, как только выполнится. С точки зрения PHP, утечки памяти — это нормально.

Речь не только о памяти


Дальше больше. Если вы использовали PHP довольно часто, то вам наверняка должна быть знакома вот эта проблема:

Fatal error: Exception thrown without a stack frame in Unknown on line 0

Что это значит? Честно говоря, я не знаю. Я не могу найти строку с номером 0 в неизвестном PHP-файле. Кажется, есть такие же невежественные люди, как я. Некоторые говорят, что это связано с обработкой ошибок и исключений в PHP. Никто не знает наверняка, я же могу говорить лишь об условиях, предшествующих этой ошибке: постоянно выполняемые процессы, работающие с гигабайтными базами данных, работающие под высокой нагрузкой в реальных условиях. В действительности вы вряд ли обнаружите такие ошибки на своем локальном сервере.

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

Использование неправильных инструментов


Вы видите системность? У меня есть старые проекты, в которых PHP использовался в фоновых процессах или других местах — не в обычных web-сайтах (здесь в скобках автор пишет «yes, i'm a hyred keyboard» — прим. пер.) — но в каждом из них была одна и та же проблема. Не имеет значения то, насколько хорошо выглядит ваша идея на бумаге; если вы хотите, чтобы процессы работали постоянно, то знайте, что по тем или иным причинам они завершатся, причем быстрее всего под нагрузкой. Нет ничего такого, на что вы могли бы повлиять, потому что PHP создан, чтобы умирать. Основная особенность ядра этого языка заключается в том, что все должно самоликвидироваться, и не важно что это будет.

Для нового проекта я использую Python, virtualenv, Flask, Supervisor и Gunicorn. Я поражен, как хорошо всё это работает, насколько продуман каждый из компонентов — а ведь некоторые из них на этапе бета-тестирования. Но намного важнее то, что они действительно поддерживают работу с фоновыми процессами. Вы спросите: как они это делают? Они не делают ничего, Python просто не кончает жизнь самоубийством. Вот и все, это часть архитектуры ядра. Я не хочу сказать, что это средство от всех бед. Может, я слишком много времени программировал на PHP и просто нахожусь под впечатлением.

Заключение


Конечно, вы всегда можете найти обходной путь. Например, вы можете до смешного увеличить значение memory_limit и немного увеличить время выполнения процессов. Вы также можете поиграть с утилитой cron, shell-скриптами и другими инструментами UNIX. Вы можете использовать PHP для создания web-сайтов, а другие языки — для фоновых процессов. Но имейте ввиду, что мы говорим здесь о средних и высоких уровнях сложности, это касается не только самого языка, но и тех библиотек и инструментов, которые вы применяете, поэтому использование второго языка вместо того, который подвёл вас, может оказаться нетривиальной задачей. Это также касается тех инструментов, для которых 30-секундная задержка может привести к плачевным результатам.

Возможно, найдутся люди, которые думают, что более сервис-ориентированная архитектура может помочь преодолеть ограничения PHP. Может быть, найдутся и те, которые докажут, что PHP 5.4 и PHP 5.5 намного лучше и что язык понемногу улучшается.

К счастью, я уже пошёл дальше.

Обсуждение на HN и Reddit.

Продолжение здесь
Метки:
Поделиться публикацией
Комментарии 260
  • +23
    > unset($a);

    unset() не освобождает память вот прямо щас. Она освободится потом, во время сборки мусора. Лучше делать $a = null; если хотите ускорить освобождение.
    И кстати. bugs.php.net/bug.php?id=33595.
    Fix in PHP 5.3.

    > Если вы использовали PHP довольно часто, то вам наверняка должна быть знакома вот эта проблема:

    > Fatal error: Exception thrown without a stack frame in Unknown on line 0

    Вот чесслово, за много лет работы с PHP ниразу такого не видел.
    • +1
      Лучше делать $a = null; если хотите ускорить освобождение.
      А ещё лучше вызвать gc_collect_cycles()
      • +1
        Оно только в >=5.3.0. Да и что-то мне не нравится идея вызывать коллектор на каждый чих…
        • –3
          А идея уродовать код всякого рода $a = null; и unset($a) нравится?) Ну и если уж программиста так парит сколько PHP ресурсов кушает, то первым делом нужно до 5.3 обновиться, или даже сразу до 5.4.
          • +1
            > А идея уродовать код всякого рода $a = null; и unset($a) нравится?)

            А вы какой ответ ожидаете? :) Проблема в том, что у клиентов зоопарк разных версий. Недавно даже что-то из 4.2.х видел.
            • –1
              А в чём тут уродство? По моему C-style логика работы с памятью malloc -> free (занял память освободил то что занял) как раз и отличает продуманный, красивый, правильный код.
              • 0
                Если бы всё было так просто, то языки с автоматическим управлением памяти просто не возникли бы класс. На практике далеко не всегда получается освободить память там, где выделил, поскольку нужно передавать ссылки во «внешний мир», где контроль за их количеством теряется, если не принимать мер по «ручному» (на уровне своего кода, а не языка) автоматическому управлению памяти.
        • 0
          Разве unset() не освобождает память немедленно? В PHP вроде бы детерминированный сборщик мусора. По-моему, как только число ссылок = 0, вызывается сборщик мусора (если ссылка не циклическая).

          www.php.net/manual/en/features.gc.refcounting-basics.php
          • 0
            См. ссылку на багрепорт. И таки да, насколько я помню, он не форсирует вызов сборщика.
            • 0
              По ссылке расположен багрепорт об утечке памяти при использовании циклических ссылок.
        • +3
          Fatal error: Exception thrown without a stack frame in Unknown on line 0

          Видел такое когда исключение возникало в деструкторе класса, в моем случае это был класс обработчика ошибок.
            • +12
              Только не $a = NULL; а $a->f = NULL;
              Вам то может и очевидно, но тот кому это очевидно и сам это делает. А так можно запутаться.

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

              * Тест №1
              unset($a); unset($b); print "GC: " .gc_collect_cycles(). "\n";

              * Тест №2
              соответственно ваш (естественно с gc_disable() для чистоты эксперимента. Хотя естественно его включение кашу не испортит):
              $a->f = NULL; $b->f = NULL; unset($a); unset($b);

              * Тест №3
              в котором просто gc_enable() показал приемлемые показатели — всего на 3Мегабайта больше памяти в пике. Хотя конечно в реальных условиях это тоже существенно.

              * Тест №4
              Чистый тест (он же, но в среде 5.3 это gc_disable()) из статьи естественно показал смерть по памяти.

              Убедившись, что вариант с NULL показывает лучший результат, и при этом не требует ни 5.3, ни злоупотреблений с уборщиком мне захотелось перенести это в деструктор… Тот кто в отличии от меня внимательно читал документацию понимает чем это закончилось. Тем кто как я читал ее невнимательно поясню:
              Деструктор будет вызван при освобождении всех ссылок на определенный объект или при завершении скрипта (порядок выполнения деструкторов не гарантируется).

              Т.е. если вы ожидали как и я, что он будет вызван при unset то у меня для вас плохие новости…

              Вариант с деструктором провалился, но все равно очищать их руками это плохое решение.
              Попробовал вот так:
              * Тест №5
              <?php class Basic { function _park() { $this->__destruct(); foreach($this as $key=>$value) { $this->$key = NULL; } } function __destruct() { echo('.'); } } class FOO extends Basic { public $f; } class BAR extends Basic { public $f; } gc_disable(); while(1) { $a = new FOO(); $b = new BAR(); $a->f = $b; $b->f = $a; print "Memory usage: " . number_format(memory_get_usage(true)) . " bytes\n"; $a->_park(); unset($a); $b->_park(); unset($b); }
              Результат предсказуемо хороший (равный первым двум тестам).
              Решение конечно костыльное, но в принципе рабочее. Естественно в реальном мире метод парковки должен быть поумнее, учитывать что свойства могут быть массивами или объектами, со всеми вытекающими, да и деструктор тоже должен учитывать существование «парковки» — в нашем выводе по четыре точки на цикл, т.е. деструктор вызывается по два раза, что ожидаемо. Он должен как-то учитывать, факт того что его уже вызывали, и не выполняться повторно.

              ПЫСЫ: еще раз подчеркну — в нормальных условиях я не советую использовать ни один из описанных костылей, лучше доверится автоматическому уборщику.
              • 0
                Простите, ошибочка у меня. Я хотел вызывать деструктор из парковки для большей совместимости со старым кодом, но при здравом размышлении — раз нам все равно нужно проверять деструктор на совместимость, то пусть лучше деструктор вызывает парковку а не наоборот. Парковка спокойно сможет контролировать свое повторное использование, а убедиться в наличии parent::_destruct() проще чем каждый раз убеждаться что логика совместима…
              • –2
                Лучше делать $a = null; если хотите ускорить освобождение.

                я на собеседовании буду спрашивать чем $a = null; отличается от unset($a)
                • 0
                  Не могу не заметить, что «лучше делать $a = null; если хотите ускорить освобождение» — чушь собачья. Спрашивать вы конечно можете, но как вы хотите интерпретировать ответ?
                  • 0
                    Почему чушь? Тест показал, что это работает. И работает даже на 5.2.
                    Ну естественно если обнулять правильно, понимая о чем речь идет, т.е. $a->f = NULL; в терминах статьи.
                    Но это в принципе очевидно.
                    • 0
                      Однако же человек собирается спрашивать «чем $a = null; отличается от unset($a)». Ему вот не очевидно.
                      • 0
                        Ну это да. В качестве задачки я для себя сформулировал бы вопрос именно так: «в сети существует мнение, что для борьбы с утечками памяти и ускорения мусорщика рекомендуют делать $a = NULL; вместо unset. Каково ваше мнение на сей счет, правильно ли так поступать, приведите пример того как именно правильно поступать.»
                        И пусть он мне объясняет, что нужно именно ссылку обнулять, а не всю переменную, что это лучше использовать не вместо а вместе и т.п. Ну и даже если не всё объяснит, то ход мысли может много показать. Особенно если дать возможность прямо на месте погуглить да потестить :)
                        • 0
                          Мой ответ был бы примерно таким: «да, были вроде какие-то костыли для официально больше неподдерживыаемых версий PHP, но по скорости это экономия на спичках типа использования одинарных кавычек вместо двойных, а unset($a) куда семантичнее $a = NULL в данном контексте. Буду формировать свое мнение, когда это действительно узким местом станет в приложении».
                          • 0
                            вы не приняты. ибо разница есть и она принципиальна.
                            • 0
                              <?php
                              
                                  $a = 12;
                                  echo ' --  ';
                              
                                  $a = null;
                              
                                  if($a) echo '111';
                              
                                  unset($a);
                              
                                  if($a) echo '222';
                              
                              
                              • 0
                                ну и по мелочи
                                $a = 5;
                                $b = &$a;
                                unset($b); 
                                print $a; 
                                
                                
                                $a = 5;
                                $b = &$a;
                                $b = null;
                                print $a; 
                                
                                
                                $a = array('test' => 1);
                                $a['test'] = NULL;
                                echo "Key test ", array_key_exists('test', $a)? "exists": "does not exist";
                                
                                
                                
                                $a = array('test' => 1);
                                unset($a['test']);
                                echo "Key test ", array_key_exists('test', $a)? "exists": "does not exist";
                                
                                
                                • 0
                                  Разницу между unset и null я прекрасно понимаю (к слову E_ALL принудительно включаю в коде, без этого первый пример не очень показателен). Но использовать null вместо unset для освобождения памяти — костыль и для него нужны основания, которых я не знаю и не помню.
                              • +1
                                Я разве утверждал, что разницы нет? Просто уже давно не сталкивался с подобными проблемами (утечки памяти и тормоза сборщика — с последней вообще ни разу), в том числе и при разработке демонов на PHP, и потому не помню нюансы, а для освобождения памяти буду использовать (и использую) предназначенные для этого механизмы, пока не столкнусь с проблемами. Если $a = NULL используется только для борьбы с утечками памяти и ускорения сборщика мусора, не имея самостоятельного семантического значения, то это костыль, а костылей в своем коде я стараюсь избегать. Хотя бы потому что их нужно комментировать и желательно на английском, а мне лень в словари и справочники лезть.
                                • 0
                                  Более прозрачным является не отказ в пользу автоматического gc а его ручной вызов в узких местах.
                                  Мои тесты показали, что оптимальные схемы кушают 0,5Мб, а схема с мусорщиком кушает 3Мб.
                                  Если структуры будут чуть больше чем пустышки которые идут в тестах, то разница может оказаться и существеннее.
                                  Вообще это все холивар.
                                  Лично я бы на собеседовании рассказал бы о теоретической базе того, почему такой костыль может работать (о циклических ссылках), и сказал бы что это костыль, и как он работает я на практике не знаю (Ну в естественных условиях конечно. Если бы не эта статья я фиг бы стал тести писать да запускать :) )
                      • +1
                        но как вы хотите интерпретировать ответ

                        unset уничтожает и имя в словаре и zval
                        $a = null освобождает старый zval, создает новый с null и не уничтожает имя в словаре.
                        • 0
                          дальше можно поспрашивать про циклические ссылки и GC
                          • +1
                            Думаю, после ответа «unset уничтожает и имя в словаре и zval» можно уже не спрашивать :) Тем более, что сейчас проблемы циклических ссылок по сути нет, а в ручном управление gc необходимость возникает крайне редко.
                          • 0
                            Никакой. Считаю, что PHP из-за слабости сборщика мусора не подходит для написания долгоживущих приложений.

                            А как бы вы интерпретировали такой ответ?
                            • 0
                              Стереотип :)
                      • 0
                        Вы не видели, а она-то была. Просто самоуничтожилась )
                        • 0
                          Так вроде ж уже разобрали, что это связано с исключениями в деструкторах.
                      • +2
                        Странно что риквесторов срача нету, видимо по выходным они отдыхают!
                        • +14
                          наверняка, на вашем хостинге за 5 долларов в месяц нет доступа по SSH, утилиты cron или похожего инструмента.

                          Что за бред про хостинг без cron? У нас тут в РФ хостинг за 3 доллара с cron и это не самые низкие цены. SSH обычно в таком случае нету, но именно cron решает приведённую задачу. Т.е., это целый абзац ни о чём.
                          • 0
                            В свое время нужно было запускать скрипт опроса почты (что-то вроде нотификатора) каждую минуту. Выяснилось, что хостер позволяет минимум раз в три минуты. И действительно, пришлось извращаться. Запускать скрипт раз в три минуты, а там делать цикл от 1 до 3 с задержками по минуте. Работало нормально в течение нескольких месяцев. Но ощущение кривизны оставалось. :)
                            • 0
                              В США есть и VPS за 5 долларов, более того, даже на бесплатных зарубежных хостингах есть cron (SSH и правда нет).
                              • 0
                                да вроде и с ssh встречались.
                                • 0
                                  Поделитесь в личку, а то, я что то не встречал. Гоудадди 15 вроде самое дешевое, что видел.
                              • +1
                                У нас тут в РФ хостинг за 3 доллара с cron и это не самые низкие цены.
                                Да, даже в 7 раз дешевле — и то cron есть
                                Скриншот тарифов одного хостера
                                • +2
                                  Не сочтите за рекламу, но можно снять даже vds-сервер за 2,9$
                                • +3
                                  Да меня тоже рассмешило, начинает за здравие, кончает за упокой — ведь в статье речь идет об enterprise разработке, какой еще говнохостинг?:)
                                  В общем, все проблемы, кроме лексических, затронутые в статье решаемы другими сервисами. Тот же memcached/apc. Любой действительно сильный программист прекрасно осознает однопоточность php и использует его соответственно — как интерфейс к нужным демонам, если они нужны в программе. Автор — истеричка.
                                • +22
                                  >>> Для нового проекта я использую Python, virtualenv, Flask, Supervisor и Gunicorn. Я поражен, как хорошо всё это работает
                                  о да, чувак. тебя ждет много открытий…
                                  да, я вижу что перевод ))
                                  • 0
                                    Занятно, тоже хотел заняться переводом этой статьи :)
                                    Перевод, кстати, отличный! Теперь Вы обязаны перевести продолжение, чтобы полностью раскрыть тему :)
                                    • 0
                                      Спасибо, но насчет качества перевода — это все-таки громко сказано) Ошибок море.
                                    • +7
                                      Ждём вторую сторону со статьёй «PHP похоронит хоронителей».
                                      • +6
                                        или «PHP переживёт хоронителей» :)
                                      • +12
                                        > наверняка, на вашем хостинге за 5 долларов в месяц нет доступа по SSH, утилиты cron или похожего инструмента
                                        Стало понятно, на кого ориентирована данная статья.
                                        • +2
                                          Меня еще больше порадовал связка:
                                          наверняка, на вашем хостинге за 5 долларов в месяц нет доступа по SSH, утилиты cron или похожего инструмента
                                          Но псевдослучайность на выборке из n-сотен нельзя сопоставлять с тысячами запросов в минуту. Задачи, которые должны запускаться через определенное время, на деле обрабатываются несколько раз в мгновение ока. Начинают происходить забавные вещи...

                                          Боюсь, на пятидолларовом хостинге, при таких нагрузках, забавные вещи начнут происходить не только от этого.
                                        • +8
                                          Интереса ради запустил код из статьи на 5.3, добавив время выполнения и количество итераций.

                                          3641089 iteration. 117 sec. Memory usage: 7,864,320 bytes
                                          6642159 iteration. 216 sec. Memory usage: 7,864,320 bytes

                                          дальше ждать не стал, но, думаю, понятно. Претензии к хостингу за 3 бакса тоже неясны, надо было уже сразу шаровые хостинги брать, 3$ это сильно много для серьезного проекта.

                                          В общем, претензий к php много (как и к любому популярному ЯП. ну может немного больше), но автор уже давно не в теме и то что он пишет давно устарело.
                                          • +5
                                            Автор оригинала начинал еще во времена мамонтов. У наго сложились неразрушимые стереотипы, либо он уже не так сильно интересуется нововведениями и фиксами в новых версиях PHP.
                                            • +3
                                              По-моему, так можно сказать о бОльшей части PHP-хейтеров.
                                          • +7
                                            Хороший язык для своих задач. Для фоновой работы использую java приложения. На php все остальное, не вижу проблемы в том что php рождается и умирает на каждый запрос. Благодаря этому снижается уровень вхождения. Аппсервер трубует от разработчика более глубоких знаний и опыта, а зачем мне как начальнику искать редкого разработчика на RoR?! Если за эти же деньги я найму двух или трех на php. Если бы все писали сайты на asp.net, java и тд. то сайты стоили бы гораздо дороже.
                                            • –1
                                              А есть ли толк от «программиста», которого прельстил низкий уровень вхождения? Эти ребята, не осилившие поднять окружение для RoR или Django (соответственно, с большой вероятность не осилившие какой-нибудь адекватный фреймворк на PHP) — они правда стоят своих денег?
                                              • +4
                                                Зачем маленькой конторке RoR разработчик за 100K? Мы друг друга не понимаем… Простой сайт стоит ~30K Директор умрет с голоду=)
                                                • –1
                                                  Если работа ваших программистов состоит в незначительных допиливаниях CMS-ок в процессе создания сайтов за 30K — то, наверное, действительно нет никакого смысла менять положение вещей. Разработчики на RoR обычно занимаются задачами несколько другой весовой категории. Вы упомянули RoR, и я грешным делом подумал, что ваши специалисты решают такие же задачи. :)

                                                  • 0
                                                    Это я и писал в строчке «хороший язык для своих задач».
                                                    • –1
                                                      Для джумлы и битрикса — да, лучший. :)
                                                      • +13
                                                        ну да, джумлы, битрикса, фейсбука там…
                                                        • +6
                                                          Забыли VK, сайты WikiMedia (Википедию и прочие) и вообще все, что на движке MediaWiki.
                                                          • +3
                                                            Да не забыл, если честно, не стал шокировать сразу человека
                                                        • –3
                                                          я вас так обидел что даже в карме отметились у меня?)
                                                          • –8
                                                            Нет. Хотя после вот этого вашего сообщения всерьёз подумываю это сделать.
                                                  • +1
                                                    на ассемблер взглянуть не хотите? я слышал офигенный язык, и плевать что порог вхождения высокий, зато каждый такт оптимизируем!
                                                    • +6
                                                      Не такой уж высокий порог. Помню много чего писал еще в школе (91 — 97 годы), сначала на спектруме, потом на писюках, еще на 286.
                                                      Конечно не всю программу, но низкоуровневые вещи и узкие места да, на ассемблере. До 30% всего кода бывало на нем.
                                                      А уровень у меня тогда был ой какой невысокий.
                                                      До сих пор по себе вижу, что фраза о том, что «человек изучавший бейсик потерян как программист» — не то чтобы совсем уж беспочвенна :)
                                                      • 0
                                                        С того времени ассемблер стал совсем другим ;)
                                                      • +5
                                                        Предлагаю вам не использовать в дискуссиях ссылки на вещи, о которых вы только «слышали». :)

                                                        У ассемблера достаточно низкий порог вхождения, в особенности, если говорить о процессорах попроще, типа i8080 (всего 79 команд) или там Z80.

                                                        При программировании на ассемблере, вся сложность не в языке (он простой до невозможности, реально за несколько вечеров можно запомнить весь набор команд того же i8080, а за неделю научиться достаточно эффективно ими манипулировать), а в том, что работа ведется на очень низком уровне, из-за чего для решения относительно простых задач приходится писать относительно дофига кода. Ну и нужно ориентироваться в железе (память, прерывания, вот это вот все).
                                                        • –1
                                                          В том то и дело, я имел ввиду что поддерживать архитектуру уровня современных средних веб приложений на ассемблере будет проблематично для новичка.
                                                          • +4
                                                            Для «старичка» тоже. И скорее не «проблематично», а глупо (очень глупо) и неэффективно. Но, повторюсь, это не имеет никакого отношения к порогу вхождения в ассемблер.
                                                            • 0
                                                              Мало того, современные компиляторы и интерпретаторы с теми же задачами справляются практически не хуже :)
                                                  • +6
                                                    Это все конечно понятно. Но бОльшая часть сайтов не имеет никаких «фоновых процессов», и PHP отлично с ними справляется. А разработчикам СЛОЖНЫХ проектов эта статья не откроет ничего нового.
                                                    • +2
                                                      Довольно многие задачи в большой части сайтов правильнее было бы решать в фоне, хотя бы после отдачи клиенту ответа. И это не говоря о необходимости инициализации приложения при каждом запросе.
                                                    • +16
                                                      Почему-то мне разработчики php начинают напоминать разработчиков Delphi, точно такое же массовое желание оправдываться и судорожные поиски плюсов, а еще вечный перевод стрелок.
                                                      • 0
                                                        Ну доказать болвану обратное все-таки лучше, чем молча игнорировать его. Хотя… называйте это оправдыванием, если хотите, но лично мне очень неприятно видеть новичка, у которого все впереди, который ссылается на такие статьи!
                                                        • 0
                                                          Такое желание возникает после массовых обвинений в некомпетентности разработчиков php, типа другой ЯП они не осилили. Можно подумать, что принципы программирования различны и всегда есть возможность выбора языка.
                                                          • +1
                                                            Вот вот. Согласен на 100%
                                                            Не могу назвать себя совсем уж зеленым разработчиком. С 1989, когда я написал свою первую программу (да, в 9 лет), я писал и на Си (без плюсов правда), и на трех ассемблерах (теоретически даже четырех, но z80 и к580 считать разными языками как-то глупо — хотя переключаемый набор регистров и дает некоторую архитектурную гибкость), писал на VB, VBA, много писал на Паскаль (Делфи ни разу не запускал, не застал), родным языком для меня был бейсик, еще тот — с номерами строк, хотя и на более приличных диалектах понятно тоже писал… На питоне писал мало, но синтаксис более-менее помню. Понятно что про JS+JQuery и тому подобное даже речь не идет.

                                                            Сейчас пишу на пхп и 1С. В пхп мне не хватает жесткой типизации и порядка в функциях, но в целом жить можно.
                                                            Мой выбор пхп основывается на его распространенности, но не буду лукавить — то, что синтаксис простой это тоже подкупает. Мне лично лень вспоминать какой из вариантов массивов мне лучше подходит в данной ситуации, равно как мне лень писать каждый раз запросы ручками — мне проще один раз написать ORM и кататься на этом велосипеде.
                                                            (Объяснять почему 1С думаю не нужно).

                                                            Я сейчас собираю довольно большой движок, и мой выбор это пхп+мускул в качестве основной платформы. И да, я знаю mongo и да, она мне подходит намного лучше… но монго не стоит на каждой тачке. Так что мускул, и самые простые запросы, чтобы легко было переезжать на любой другой драйвер базы данных.
                                                            А пхп как по мне так реально недостаточно простой, я бы его упростил :)
                                                        • –2
                                                          Вывод простой. Для бэкенда PHP не годится, используйте что-то другое. Для фронтенда же вполне, если использовать его на современном уровне. Общаться с бэкендом по HTTP PHP умеет прекрасно.

                                                          (Не берем в расчет сверхвысокие нагрузки, разумеется.)
                                                          • +4
                                                            То есть фейсбук и вконтакте это не «сверхвысокие нагрузки»?))
                                                            • +11
                                                              Думаю, что в упомянутых вами случаях помимо PHP используется еще столько всякого разного, что получается как в истории про суп с топором. )
                                                              • +2
                                                                Судя по созданию инструментов типа hiphop, на php нагрузка там весьма существенная.
                                                                • +1
                                                                  Доказательство? очень просто гнобить язык, а заслуги «крутых» проектов приписывать «дополнительным» компонентам.
                                                                  • +1
                                                                    Да тот же вышеупомянутый hiphop, например (грубо говоря, самописный транслятор PHP в C++ для последующей компиляции в бинарный исполняемый файл).
                                                                    • 0
                                                                      Он уже не транслятор, а виртуальная машина с JIT-компиляцией.
                                                                      • +2
                                                                        Тоесть вы хотите сказать, что если из скрипта другого языка(питон, руби и.т.п) сделать скомпилированную программу, то оно не будет работать быстрее) Изначально эти проекты были на php и работали справляясь со своей задачей.

                                                                        Никто не спорит, что скомпилированная программа будет быстрее, но разве это проблема скриптового языка?)
                                                                  • 0
                                                                    ну каша же, а не суп
                                                                    • –2
                                                                      Google знает миллион страниц о каше с топором и четверть миллиона о супе с топором. Ваш вариант более популярен, но и мой имеет право на жизнь. :)
                                                                • НЛО прилетело и опубликовало эту надпись здесь
                                                                  • +1
                                                                    Слово «фронтенд» в контексте веб-программирования как-то имеет два значения — клиент-сайд и сервер-сайд.
                                                                    • НЛО прилетело и опубликовало эту надпись здесь
                                                                      • 0
                                                                        С этой точки зрения и фронтенд может иметь несколько слоев. В том числе и серверную часть. Собственно, бОльшая часть веб-приложений — это прослойка между пользователем и СУБД-бэкендом :)
                                                                        • НЛО прилетело и опубликовало эту надпись здесь
                                                                          • +2
                                                                            Скорее надо вводить понятие «миддленд» для трехзвенной архитектуры. :)
                                                                            • 0
                                                                              По-моему, существующее понятие "middleware" как раз об этом.
                                                                • +21
                                                                  Я не понимаю что не так-то? Скрипт — это то что выполнилось и умерло. Надо это запомнить и принимать как данность. Зачем на php писать демонов? Он не заточен под это — и не надо. Не надо чтобы php решал все возможные задачи, он и так умеет многое.
                                                                  • +3
                                                                    На современных версиях php можно и демонов писать. Надо или не надо, это уже вопрос отдельный и зависит, скорее, от ситуации. И то, что язык уже это позволяет, пусть и с оговорками, это большой плюс.
                                                                    • +7
                                                                      Надо сказать, что автор топика совершенно прав про то, что php чуть что — умирает. Он не может восстановиться, например, после fatal error-а, а его получить очень легко.

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

                                                                      И утечки памяти есть точно так же в любом языке — например, при использовании внешних библиотек. От них никуда не деться. Поэтому приходится делать разные watchdog-и, делать fork с последующим убиением потомка при обработке «тяжелых» задач и т.д.
                                                                      • –1
                                                                        fatal error'ы можно контролировать. Как правило, к ним приводит или глючный код (который нужно отлаживать, как и в случае любого языка) или перерасход ресурсов. Последнее, в принципе, является частным случаем первого и тоже актуально для всех языков.

                                                                        Причин возникновения fatal error не так много и словив его единожды, достаточно просто переделать код таким образом, чтобы в этом месте он больше не появлялся.
                                                                        • 0
                                                                          На самом деле может быть очень много причин перехватывать фаталы.
                                                                          платформа не всегда может однозначно определить является ли ошибка recoverable_error или нет.
                                                                          Частично я с вами конечно согласен, но с другой стороны не вижу причин ограничивать разработчика.
                                                                          Теоретически могут быть случаи когда и для E_PARSE можно найти воркарраунд.
                                                                          И в таких ситуациях разработчика загоняют в eval или в некие пляски с бубном типа php_strip_whitespace в spl_autoload_register.
                                                                          • 0
                                                                            Вообще-то, я не предлагал ничего перехватывать. Получаем ошибку, демон падает, исправляем ошибку и запускаем заново. Это касается любого яп (где-то я уже это писал).
                                                                            • +2
                                                                              хм… вы точно это мне написали?
                                                                              Перечитайте мое сообщение.

                                                                              Но раз уж парсинг моего сообщения вывалился у Вас с фаталом, то приведу пример для лучшего восприятия:
                                                                              Система выполняет некоторый код, потом подбирает свежеполученный код, к примеру залитый админом или вебмастером. Этот код падает с фаталом. Пусть даже с E_PARSE, не суть.
                                                                              Часть логика требует после подобного краша отправить автору этого изменения уведомление типа «Друг, ты мне что-то не то залил, оно в фатал валится, разберись пожалуйста», и… продолжить работу системы дальше.
                                                                              Ведь остальные модули работают нормально, да и даже при условии если ситуация слишком нестабильна, и мы решаем всё остановить до разбирательства с погибшим модулем, все равно тех кто живой нужно корректно остановить.

                                                                              Ну или какое-то расширение выбросило фатальную ошибку когда столкнулась с проблемами с диском.
                                                                              Мы знаем свое окружение, знаем что можно сделать чтобы проблему решить (очистка диска, ремонт квот и т.п.), но мы уж в фатале, и retry нам не светит…

                                                                              Ну или банально — у меня обработчик ошибок сохраняет в удобочитаемом виде логов на несколько мегабайт (естественно не на продакшене). Но это не касается фаталов — их мне не перехватить.
                                                                              И не потому что технически это невозможно — просто разработчики решили, что мне это не нужно.
                                                                              • –1
                                                                                Весьма интересная точка зрения, но все таки Fatal'ы они на то и фатальны, это значит что система сильно нестабильна я может выкинуть те еще фокусы. Чтобы вебмастер/админ не заливал файлы в продакшн есть методики вроде CI и тесты. Тогда все те оставшиеся фаталы посте тестов буду относиться скорее к оборудованию.
                                                                                Не хватает памяти? ну и что мы будем делать? не факт что хватит памяти ее очистить (нестабильность). Проблемы с диском? а если сейчас __autoload захочет подгрузить какой класс? все, приехали.

                                                                                Насчет логгирования stackoverflow.com/questions/277224/how-do-i-catch-a-php-fatal-error
                                                                                • +4
                                                                                  Этот хак знаю, и использую. Но хак он хак и есть. Иногда бывает, что он не срабатывает. Не могу что-то конкретное сказать, не успел выйти на повторяемость.

                                                                                  Что касается попыток восстановления, то да, часто они будут неудачны, но зачем же разраба специально в этом ограничивать? Я понимаю, что если я буду писать систему управления ядерным реактором или даже коптером на пхп, то я сам себе злобный буратино. Но давайте рассмотрим пример с коптером:
                                                                                  Висит себе наша вертушка на высоте 5к, вдруг видит впереди чечевица висит.
                                                                                  Модуль взаимодействия с объектами чечевицеобразной формы у нас прошел тестирования в тренажере, но поскольку инопланетяне прилетают к нам не так часто, то в реальных условиях он был протестирован слабо.
                                                                                  Чечевица выполняет банальный маневр — телепортируется на километр в сторону.
                                                                                  Анализатор траектории объекта в панике, паника заканчивается крашем по памяти.
                                                                                  Теоретически мы могли бы подчистить память, к примеру удалив малокритичные данные, или просто перейти на радиоуправление, благо под него уже память выделена… много чего можно было бы сделать. Но вместо этого мы падаем с фаталом… в общем то в прямом смысле падаем :)

                                                                                  Чуть более реальный пример.
                                                                                  Есть некая система… ну скажем биллинг, ну или IVR, не суть (не могу конкретнее описать не нарушив NDA).
                                                                                  В системе регулярно (порядка десяти раз в день) добавляются и удаляются новые алгоритмы поведения в тех или иных ситуациях (новые сценарии связанные с новыми клиентскими задачами).
                                                                                  Да у ребят целый штат тестеров и т.п., но все равно изредка некоторые модули таки падают с фаталом. (раз в пару месяцев). Да, потом архитектуру поменяли, и теперь все независимые вещи работают независимо (fork), тоже еще тот костыль, но это было лучше чем фаталы.
                                                                                • 0
                                                                                  Перехватить фаталы можно с помощью register_shutdown_function() + error_get_last().
                                                                          • 0
                                                                            Система должна самостоятельно уметь восстанавливаться после смерти в любой произвольный момент времени [...]

                                                                            К сожалению, для большинства случаев это утопия, а потому я бы сместил планку пониже: система должна предоставлять инструменты для контроля смерти, или, на худой конец, — жизни %P Примерно об этом и пишет автор.
                                                                            • 0
                                                                              Не вижу в этом ничего утопичного. Это практика жизни скорее. Вот ушла у вас машина в LA=20, вы видите, что все ресурсы ест расплодившийся демон, даже знаете, где в нем ошибка. Что вы сделаете? Убъете его (в худшем случае — через 9-й сигнал). Вот это и есть «смерть в непредсказуемый момент времени». В готовности к ней ничего такого страшно сложного нет, надо просто а) использовать транзакции, и б) соблюдать идемпотентность во внешних API.
                                                                              • 0
                                                                                Не понял, как это относится к «самостоятельному» восстановлению. Вот если бы вы мне описали, как этот демон мониторится, какие факторы используются для трактовки его смерти/недоступности, какими средствами он автоматически ликвидируется, и какой механизм используется для его восстановления, как эксплуататор api умеет и пытается повторить упущенные за время простоя демона шаги, это можно было бы как-то считать самостоятельностью.

                                                                                Очевидно, мы с вами подразумеваем под системой разные её уровни, либо вовсе разные вещи.

                                                                                В общем, комментарий задумывался о том, что самостоятельность восстановления системы в большинстве случаев избыточна (если, конечно, мы не говорим о системе жизнеобеспечения на php %)) или неподъёмна/недостижима в текущих условиях.
                                                                        • НЛО прилетело и опубликовало эту надпись здесь
                                                                          • 0
                                                                            Тот самый fastcgi который магическим образом работает без изменения строчки кода?
                                                                            • НЛО прилетело и опубликовало эту надпись здесь
                                                                            • +2
                                                                              В PHP прирост мало заметен (по сравнению с классическим mod_php для Apache), потому что касается только взаимодействия с веб-сервером, а модель «ответил на запрос и умер» все равно осталась на уровне приложения, состояние между запросами не сохраняется, что, как минимум, вызывает необходимость полной инициализации приложения при каждом запросе, не говоря о невозможности организовывать кешерирование бизнес-данных внутри процесса без использования средств IPC, включая сетевые.
                                                                              • +1
                                                                                Есть и реализации fastcgi в userland. Тот же phpDaemon. Или wsgi в appserver-in-php
                                                                                • 0
                                                                                  Я про «из коробки» конечно.
                                                                                • НЛО прилетело и опубликовало эту надпись здесь
                                                                                  • +2
                                                                                    Именно это и имел в виду. Php-fpm является fcgi сервером, но приложение остается CGI, fast по сути нет, плюсы в других плоскостях. лежат. В PHP нет штатной (в mod_php или php-fpm) возможности использовать одну «глобальную» переменную для разных запросов, если не напишешь свой сервер (http или fastcgi — не суть) для php-cli, что делать на PHP исторически не принято, как по объективным (значительные утечки памяти в недавнем прошлом), так и по субъективным причинам, да и в стандартной библиотеки толком никакой поддержкки нет, только биндинги к функциям ОС для сокетов и процессов. Сейчас проблем с памятью значительно меньше (и это просто локальные баги типичные для Си, а не концептуальные недостатки алгоритмов), но как-то не заметно появление чего-нибудь сравнимого с Tornado или Twisted по популярности, не говоря о стандарте типа WSGI в принципе. Есть вполне годный PhpDaemon, но популярные фреймворки и CMS его напрямую не поддерживают и требуют ручного затачивания, если оно вообще представляется возможным без глобальных переделок (глобальные или статические переменные, завязанные на запрос, основная проблема).
                                                                              • 0
                                                                                а как же холивары на пустом месте? :'|
                                                                                • +1
                                                                                  Поздно, его уже выпустили daemon.io/
                                                                                  • +3
                                                                                    Современные веб приложения становятся все сложнее и сложнее, и постепенно отходят от концепции одноразовой генерации веб странички раз в час. Сейчас веб приложение — это long lived connection, взаимодействие с открытой веб страничкой у пользователя, находящися в памяти контекст. Соответственно, используются механизмы, позволяющие не запускать интерпретатор на каждый запрос, а держать интерпретатор в пямяти с загруженным «ядром» приложения и скармливать ему запросы по мере поступления. Так работыют WSGI, PSGI, rack. Автор указал, что PHP так не работает — что в рамках теорикрафта знать неплохо, особенно тем, кто не работает с PHP плотно на протяжении последних десяти лет, но тенденции знать должен :)
                                                                                    • 0
                                                                                      Не превращайте php в кухонный комбайн.
                                                                                      • 0
                                                                                        Я не понимаю что не так-то? Скрипт — это то что выполнилось и умерло.

                                                                                        Скажу больше, такое поведение больше всего соответствует модели работы протокола HTTP. Даже более того, такой подход лучше, чем когда ответы на HTTP запросы выполняет долгоживущий процесс, в том, что способствует снижению кол-ва человеческих ошибок при написании кода и является более безопасным (в долгоживущий процесс, при наличии ощибки, можно внедрить вредоносный код, который будет продолжать выполняться всё время жизни процесса).
                                                                                        • 0
                                                                                          В этом лучше (и чисто теоретически), но по другим вполне объективным практическим критериям хуже. Плюс ситуация HTTP over TCP/IP явно предусматривает наличие долгоживущих процессов, а в «cgi-based скрипты» (которые вполне могут быть на компилируемых языках типа Си или вообще Ассемблера) лишь выводят часть логики единого (для клиента) сервера…
                                                                                          • 0
                                                                                            HTTP основан на кратковременных запросах (постоянного соединения с клиентом он не поддерживает), так по какой причине использование HTTP стало вдруг явно предусматривать наличие долгоживущих процессов?
                                                                                            • 0
                                                                                              80-й (или другой) порт кто-то же должен постоянно слушать. Может, конечно, не явно, но во всех популярных ОС вроде как порты слушают именно долгоживущие процессы, а не при начале коннекта процессы запускаются (форканье основного процесса несколько не то уже, не говоря о префорке)…
                                                                                              • 0
                                                                                                При коннекте, как бы, тоже можно запустить (см. inetd). Просто оно очень медленно выходит.
                                                                                                • 0
                                                                                                  В inetd вроде как даже буква d намекает, что процесс долгоиграющий. То что он потом запускает другие уже детали реализации. По типу apache+php-cgi.
                                                                                                  • 0
                                                                                                    Ну представьте себе, что функциональность inetd мы вкрутим в ядро (наподобие того, как работает модуль icmp). Процесса нет, но что изменилось? Все равно в первом приближении часть, занимающаяся приемом соединений у всех сетевых демонов схожа. Серьезные различия начинаются только на уровне вышестоящего протокола.
                                                                                                • 0
                                                                                                  Долгоживущий слушающий процесс не занимается исполнением кода скрипта сайта. Нас же ведь интересует процесс, который непосредственно занимается обработкой кода для пришедшего HTTP запроса?! Я противопоставляю обсуждаемой модели работы PHP модель при которой в долгоживущем слушающем процессе исполняется код самого скрипта.
                                                                                                  • +1
                                                                                                    Возможны различные реализации исполнение кода скрипта (смотря что считать скриптом, правда). В PHP сейчас стандарт де-факто — максимально совместимая с CGI (и, как следствие, максимально использующая такие per request фичи, даже киллер-фичи можно сказать, PHP как суперглобалы типа $_REQUEST или $_SESSION), а проще говоря режим неинтерактивного CLI-приложения, запускаемого и инициализируемого для каждого запроса.

                                                                                                    При этом технически новые процессы в ОС на каждый запрос не создаются обычно, просто процессы хэндлеров заново инициализируются после каждого запроса с полным освобождением памяти занятой непосредственно скриптом (но не интерпретатором), что исключает передачи переменных из одного такого «виртуального» хэндлера в другой (не считая «костылей» типа различного вида IPC, от shmem до внешних http сервисов). И если обычные переменные ещё как-то (через сериализацию штатную или самописную, но на больших объемах довольно ресурсоемкую) можно передавать то ресурсы (php-обертки для файловых дескрипторов по сути) — нет. Такая модель по сути одна из киллер-фич, сильно снижающая порог вхождения (в большинстве случаев не нужно заботиться об освобждении памяти и дескрипторов), но в тоже время служащая препятствием для написания более эффективных приложений.

                                                                                                    Но эта модель не единственная. Даже с максимальным сохранением обратной совместимости и относительно легкой реализацией (как в плане времени разработки, так и времени выполнения) можно было бы ввести суперглобал типа $_PROCESS_RESOURCES, с «контрактом» похожим идеологически на $_SESSION и шарить хотя бы дескрипторы в рамках одного процесса, а лучше любые переменные в суперглобале типа $_PROCESS_VARS, который бы не обнулялся при каждом запросе, а существовал хотя бы до первой fatal ошибки в рамках процесса. Случайных проблем типа дедлоков это не должно вызывать (на уровне скрипта), за очень редким исключением.
                                                                                                    • 0
                                                                                                      Но почему Вы говорили, что модель работы HTTP подразумевает наличие долгоживущих процессов? Я воспринял эту фразу как долгоживучих процессов, продолжающих существовать (и сохранять состояние) после заверщения обработки конкретного HTTP запроса (т.е. не общий системные код, т.к. понятно, что различные системные долгоживущие процессы будут в любом случае, всё таки на компьютере-сервере работает операционная система с сетевыми процессами, ждущими запроса).

                                                                                                      HTTP же практически не предполагает сохранение состояния между парами «запрос-ответ» (т.е. не предполагает наличия долгоживущих процессов, остающихся после обработки конкретного зароса и сохраняющих его состояние)?! Возможности есть, но это же все таки исключение из модели работы HTTP.
                                                                                                      • 0
                                                                                                        Видимо плохо мысль выразил. Да, сама модель HTTP не предполагает наличия даже системных долгоиграющих процессов «де-юре» (может железо слушает 80-й порт и генерирует прерывание на запуск обработчика, ghb gjcnegktybb http заголовков, а вдругих случаях игнорит, а может вообще всё на уровне железа реализовано), но на практике они всегда есть. Причем не только на уровне слушателя-диспетчера-менеджера, но и обработчиков: prefork+mod_php, php-fpm и т. п. загружают предварительно интерпретатор PHP. И значительным недостатком PHP является невозможность «из коробки» загружать не только интерпретатор, но и хотя бы неизменяемую от запроса к запросу часть даных приложения типа конфигов или DI-контейнеров, или изменяемую вынужденно, типа дескрипторов, не говоря о невозможности создать внутрипроцессный (ос-процесса, а не " php-vm") кэш, издержки на который будут минимальны по сравнению даже с локальными IPC-средствами.

                                                                                                        Для многих ЯП, чуть ли не на уровне синтаксиса, это не исключение, а правило. Скорее PHP тут выглядит исключением, если рассматривать реально в современном мире применяемые подходы. Вплоть до того, что полностью пишутся http-«серверофреймворки» на языках типа Ruby, Python или JavaScript во многом на PHP похожих, а nginx или ещё какой прокси используется перед ними для отдачи статики и/или балансировки.
                                                                                        • 0
                                                                                          автор поста видимо тоже слушает radio-t :)
                                                                                          • +1
                                                                                            Дайджест интересных новостей и материалов из мира PHP за последние две недели № 16 (22.04.2013 — 06.05.2013)
                                                                                          • +1
                                                                                            По-моему сейчас скорость выполнения php кода совсем не критический параметр. Основное время выполнения занимают обращения к БД.
                                                                                            • 0
                                                                                              Это у маленьких проектов. Если проект более-менее крупный и посещаемый, то запросы к базе чаще всего кэшируются, а менеджмент этого кэша и логика рендеринга, как раз и отъедают основные ресурсы. Речь о динамических проектах, где сложно кэшировать большими блоками (или целыми страницами).
                                                                                              • +1
                                                                                                Какое-то шило на мыло. Мне тут на phpclub'е пару дней назад вдолбили простую истину — зачем бд, как если не для запросов? Зачем все подряд кешировать?
                                                                                                • 0
                                                                                                  Затем, что время обращения к кэшу на порядок (и иногда 2-3) быстрее, чем запрос к базе.
                                                                                                  • 0
                                                                                                    А что на счет свежести кеша? Частые запросы и так лежат в кеше СУБД и отдаются от туда.
                                                                                                    Подобный холивар на самом деле не основателен. Нужны тесты, для каждой конкретной ситуации, просто моя ошибка была в том, что я думал кеширование — ок, запросы — как можно меньше. Но ведь создатели СУБД — не дураки, и надо 10 раз подумать прежде чем юзать кеш
                                                                                                    • 0
                                                                                                      Обычный для PHP MySQL использует очень грубую политику инвалидации кеша, которая для многих типовых задач сводит преимущества от наличия кеша в СУБД к нулю. С другой стороны, многие сайты позволяют использовать ещё более грубую политику (на основе TTL) без заметной потери функциональности.
                                                                                                      • +2
                                                                                                        Запрос к БД сам по себе штука затратная, какой бы там кэш не стоял. Индексы поднять, данные найти, а может и sql распарсить. Уже это занимает много ресурсов, ну и кэширование в БД настроено на максимальную точность данных, потому, обычно, кэш сбрасывается в таких ситуациях, когда можно и не сбрасывать. СУБД не знает специфику проекта, не знает, где критичные данные, а где даже минутная задержка в обновлении не критична, потому ее кэш в любом случае, работает неэффективно.
                                                                                                        • +3
                                                                                                          Более того, сбрасывается он (в MySQL) для всей таблицы целиком при её изменениях, не взирая на то, задевают изменения результаты конкретного запроса или нет. То есть кэширование заточено на схему «частые чтения — очень редкие изменения».
                                                                                                  • 0
                                                                                                    А можете привести пример такого проекта? Я вот не представляю, как можно организовать систему кэширования, чтобы она тормозила все остальное. Сейчас, например, появилось много key-value хранилищ. Т.е. люди занимаются оптимизацией обращений к БД, а не оптимизацией кода на PHP.
                                                                                                    • 0
                                                                                                      Любой динамический проект с 5-6К онлайн скорее всего и будет таким примером. Система кэширования ничего не тормозит, читайте внимательнее. Кэш позволяет получить данные очень быстро и потому основное время приложение тратит на выполнение своего кода, а не на ожидание запроса к базе. И именно код становится узким местом.
                                                                                                      По этой причине, кстати, и тратятся ресурсы на различные оптимизаторы, начиная от кэшеров байт-кода, заканчивая трансляторами вроде hiphop.
                                                                                                • –1
                                                                                                  Я вот свой проект TorrentMonitor тоже писал на PHP, просто когда я 2,5 года назад за него брался, я вообще практически ничего не знал о программировании (я админ), и только за эти годы работы и развития проекта немного освоился в PHP, но при этом взялся ещё и за Python. На самом деле понимание того что PHP не совсем тот язык, на котором стоило бы такое писать пришло почти сразу, но тогда у меня небыло вариантов — всё-таки не просто так считается что у PHP низкий порог вхождения (и удобные мануалы с примерами), на Python`е я бы забросил проект, так его и не дописав, но сейчас, видя разницу в возможностях этих ЯП, посещают мысли — а не взяться ли в в скором будущем за то, что бы переписать всё с нуля, уже на Python`е.
                                                                                                  • +6
                                                                                                    На Python я бы не сказал, что порог вхождения слишком большой, он очень прост, но я бы в жизни не стал исполнять и подключать модули на Windows, это тот еще геморрой на своей жопе.
                                                                                                    • –1
                                                                                                      К слову, есть такая вещь как EPD — очень просто ставится и позволяет вдоволь поиграться с языком. На Edx ее рекомендовали к употреблению.
                                                                                                      • +1
                                                                                                        И все таки легче выполнять команду в Linux — «apt-get install python-module», нежели использовать Windows для компиляторов/интерпретаторов разных языков. Поэтому я всегда выполняю код на Linux, а Windows служит основной для IDE или старого доброго Notepad++. (Языки заточенные для определенной платформы берем в исключение)</