Pull to refresh

Comments 260

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

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

www.php.net/manual/en/features.gc.refcounting-basics.php
См. ссылку на багрепорт. И таки да, насколько я помню, он не форсирует вызов сборщика.
По ссылке расположен багрепорт об утечке памяти при использовании циклических ссылок.
Мой коммент про багрепорт был вот к этому:

как только число ссылок = 0


там как раз с этим были проблемы. Сорри если несколько сумбурно написал.
По поводу unset() — вот например:

stackoverflow.com/questions/584960/whats-better-at-freeing-memory-with-php-unset-or-var-null
www.php.net/manual/en/language.references.unset.php#69429

По ссылкам достаточно старый материал, в >= 5.3, насколько я понимаю, должно быть уже лучше со всем этим делом.
Fatal error: Exception thrown without a stack frame in Unknown on line 0

Видел такое когда исключение возникало в деструкторе класса, в моем случае это был класс обработчика ошибок.
Только не $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); }
Результат предсказуемо хороший (равный первым двум тестам).
Решение конечно костыльное, но в принципе рабочее. Естественно в реальном мире метод парковки должен быть поумнее, учитывать что свойства могут быть массивами или объектами, со всеми вытекающими, да и деструктор тоже должен учитывать существование «парковки» — в нашем выводе по четыре точки на цикл, т.е. деструктор вызывается по два раза, что ожидаемо. Он должен как-то учитывать, факт того что его уже вызывали, и не выполняться повторно.

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

я на собеседовании буду спрашивать чем $a = null; отличается от unset($a)
Не могу не заметить, что «лучше делать $a = null; если хотите ускорить освобождение» — чушь собачья. Спрашивать вы конечно можете, но как вы хотите интерпретировать ответ?
Почему чушь? Тест показал, что это работает. И работает даже на 5.2.
Ну естественно если обнулять правильно, понимая о чем речь идет, т.е. $a->f = NULL; в терминах статьи.
Но это в принципе очевидно.
Однако же человек собирается спрашивать «чем $a = null; отличается от unset($a)». Ему вот не очевидно.
Ну это да. В качестве задачки я для себя сформулировал бы вопрос именно так: «в сети существует мнение, что для борьбы с утечками памяти и ускорения мусорщика рекомендуют делать $a = NULL; вместо unset. Каково ваше мнение на сей счет, правильно ли так поступать, приведите пример того как именно правильно поступать.»
И пусть он мне объясняет, что нужно именно ссылку обнулять, а не всю переменную, что это лучше использовать не вместо а вместе и т.п. Ну и даже если не всё объяснит, то ход мысли может много показать. Особенно если дать возможность прямо на месте погуглить да потестить :)
Мой ответ был бы примерно таким: «да, были вроде какие-то костыли для официально больше неподдерживыаемых версий PHP, но по скорости это экономия на спичках типа использования одинарных кавычек вместо двойных, а unset($a) куда семантичнее $a = NULL в данном контексте. Буду формировать свое мнение, когда это действительно узким местом станет в приложении».
вы не приняты. ибо разница есть и она принципиальна.
<?php

    $a = 12;
    echo ' --  ';

    $a = null;

    if($a) echo '111';

    unset($a);

    if($a) echo '222';

ну и по мелочи
$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";

Разницу между unset и null я прекрасно понимаю (к слову E_ALL принудительно включаю в коде, без этого первый пример не очень показателен). Но использовать null вместо unset для освобождения памяти — костыль и для него нужны основания, которых я не знаю и не помню.
Я разве утверждал, что разницы нет? Просто уже давно не сталкивался с подобными проблемами (утечки памяти и тормоза сборщика — с последней вообще ни разу), в том числе и при разработке демонов на PHP, и потому не помню нюансы, а для освобождения памяти буду использовать (и использую) предназначенные для этого механизмы, пока не столкнусь с проблемами. Если $a = NULL используется только для борьбы с утечками памяти и ускорения сборщика мусора, не имея самостоятельного семантического значения, то это костыль, а костылей в своем коде я стараюсь избегать. Хотя бы потому что их нужно комментировать и желательно на английском, а мне лень в словари и справочники лезть.
Более прозрачным является не отказ в пользу автоматического gc а его ручной вызов в узких местах.
Мои тесты показали, что оптимальные схемы кушают 0,5Мб, а схема с мусорщиком кушает 3Мб.
Если структуры будут чуть больше чем пустышки которые идут в тестах, то разница может оказаться и существеннее.
Вообще это все холивар.
Лично я бы на собеседовании рассказал бы о теоретической базе того, почему такой костыль может работать (о циклических ссылках), и сказал бы что это костыль, и как он работает я на практике не знаю (Ну в естественных условиях конечно. Если бы не эта статья я фиг бы стал тести писать да запускать :) )
но как вы хотите интерпретировать ответ

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

А как бы вы интерпретировали такой ответ?
Вы не видели, а она-то была. Просто самоуничтожилась )
Так вроде ж уже разобрали, что это связано с исключениями в деструкторах.
UFO just landed and posted this here
наверняка, на вашем хостинге за 5 долларов в месяц нет доступа по SSH, утилиты cron или похожего инструмента.

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

Боюсь, на пятидолларовом хостинге, при таких нагрузках, забавные вещи начнут происходить не только от этого.
Интереса ради запустил код из статьи на 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 много (как и к любому популярному ЯП. ну может немного больше), но автор уже давно не в теме и то что он пишет давно устарело.
Автор оригинала начинал еще во времена мамонтов. У наго сложились неразрушимые стереотипы, либо он уже не так сильно интересуется нововведениями и фиксами в новых версиях PHP.
По-моему, так можно сказать о бОльшей части PHP-хейтеров.
Хороший язык для своих задач. Для фоновой работы использую java приложения. На php все остальное, не вижу проблемы в том что php рождается и умирает на каждый запрос. Благодаря этому снижается уровень вхождения. Аппсервер трубует от разработчика более глубоких знаний и опыта, а зачем мне как начальнику искать редкого разработчика на RoR?! Если за эти же деньги я найму двух или трех на php. Если бы все писали сайты на asp.net, java и тд. то сайты стоили бы гораздо дороже.
UFO just landed and posted this here
Зачем маленькой конторке RoR разработчик за 100K? Мы друг друга не понимаем… Простой сайт стоит ~30K Директор умрет с голоду=)
UFO just landed and posted this here
Это я и писал в строчке «хороший язык для своих задач».
UFO just landed and posted this here
ну да, джумлы, битрикса, фейсбука там…
Забыли VK, сайты WikiMedia (Википедию и прочие) и вообще все, что на движке MediaWiki.
Да не забыл, если честно, не стал шокировать сразу человека
я вас так обидел что даже в карме отметились у меня?)
UFO just landed and posted this here
на ассемблер взглянуть не хотите? я слышал офигенный язык, и плевать что порог вхождения высокий, зато каждый такт оптимизируем!
Не такой уж высокий порог. Помню много чего писал еще в школе (91 — 97 годы), сначала на спектруме, потом на писюках, еще на 286.
Конечно не всю программу, но низкоуровневые вещи и узкие места да, на ассемблере. До 30% всего кода бывало на нем.
А уровень у меня тогда был ой какой невысокий.
До сих пор по себе вижу, что фраза о том, что «человек изучавший бейсик потерян как программист» — не то чтобы совсем уж беспочвенна :)
С того времени ассемблер стал совсем другим ;)
UFO just landed and posted this here
В том то и дело, я имел ввиду что поддерживать архитектуру уровня современных средних веб приложений на ассемблере будет проблематично для новичка.
UFO just landed and posted this here
Мало того, современные компиляторы и интерпретаторы с теми же задачами справляются практически не хуже :)
Это все конечно понятно. Но бОльшая часть сайтов не имеет никаких «фоновых процессов», и PHP отлично с ними справляется. А разработчикам СЛОЖНЫХ проектов эта статья не откроет ничего нового.
Довольно многие задачи в большой части сайтов правильнее было бы решать в фоне, хотя бы после отдачи клиенту ответа. И это не говоря о необходимости инициализации приложения при каждом запросе.
Почему-то мне разработчики php начинают напоминать разработчиков Delphi, точно такое же массовое желание оправдываться и судорожные поиски плюсов, а еще вечный перевод стрелок.
Ну доказать болвану обратное все-таки лучше, чем молча игнорировать его. Хотя… называйте это оправдыванием, если хотите, но лично мне очень неприятно видеть новичка, у которого все впереди, который ссылается на такие статьи!
Такое желание возникает после массовых обвинений в некомпетентности разработчиков php, типа другой ЯП они не осилили. Можно подумать, что принципы программирования различны и всегда есть возможность выбора языка.
Вот вот. Согласен на 100%
Не могу назвать себя совсем уж зеленым разработчиком. С 1989, когда я написал свою первую программу (да, в 9 лет), я писал и на Си (без плюсов правда), и на трех ассемблерах (теоретически даже четырех, но z80 и к580 считать разными языками как-то глупо — хотя переключаемый набор регистров и дает некоторую архитектурную гибкость), писал на VB, VBA, много писал на Паскаль (Делфи ни разу не запускал, не застал), родным языком для меня был бейсик, еще тот — с номерами строк, хотя и на более приличных диалектах понятно тоже писал… На питоне писал мало, но синтаксис более-менее помню. Понятно что про JS+JQuery и тому подобное даже речь не идет.

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

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

(Не берем в расчет сверхвысокие нагрузки, разумеется.)
UFO just landed and posted this here
Судя по созданию инструментов типа hiphop, на php нагрузка там весьма существенная.
Доказательство? очень просто гнобить язык, а заслуги «крутых» проектов приписывать «дополнительным» компонентам.
UFO just landed and posted this here
Он уже не транслятор, а виртуальная машина с JIT-компиляцией.
Тоесть вы хотите сказать, что если из скрипта другого языка(питон, руби и.т.п) сделать скомпилированную программу, то оно не будет работать быстрее) Изначально эти проекты были на php и работали справляясь со своей задачей.

Никто не спорит, что скомпилированная программа будет быстрее, но разве это проблема скриптового языка?)
UFO just landed and posted this here
UFO just landed and posted this here
UFO just landed and posted this here
Слово «фронтенд» в контексте веб-программирования как-то имеет два значения — клиент-сайд и сервер-сайд.
UFO just landed and posted this here
С этой точки зрения и фронтенд может иметь несколько слоев. В том числе и серверную часть. Собственно, бОльшая часть веб-приложений — это прослойка между пользователем и СУБД-бэкендом :)
UFO just landed and posted this here
Скорее надо вводить понятие «миддленд» для трехзвенной архитектуры. :)
По-моему, существующее понятие "middleware" как раз об этом.
Я не понимаю что не так-то? Скрипт — это то что выполнилось и умерло. Надо это запомнить и принимать как данность. Зачем на php писать демонов? Он не заточен под это — и не надо. Не надо чтобы php решал все возможные задачи, он и так умеет многое.
На современных версиях php можно и демонов писать. Надо или не надо, это уже вопрос отдельный и зависит, скорее, от ситуации. И то, что язык уже это позволяет, пусть и с оговорками, это большой плюс.
Надо сказать, что автор топика совершенно прав про то, что php чуть что — умирает. Он не может восстановиться, например, после fatal error-а, а его получить очень легко.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Порадуйте меня и расскажите о своем пути:-)
Готов поспорить, что получится статья в стиле «я хз как тут и чо, но пайтон говорят получше»))

Насчет низкого порога вхождения — Вы не правы. То есть да, на «похапэ» можно достаточно быстро написать что-нибудь тривиальное, но на PHP можно написать программу, которая будет быстрее, выше, сильнее, чем на любом другом ЯП!

Я пришел в PHP после C/C++ (плюсы в основном использовал как «Си с классами и возможностью всех запутать, сделав переопределение оператора +» много лет назад, во времена PHP3, и с тех пор с ним не «разводился», только «изменял» с другими (но не с C/C++). Готов поспорить, что напишу веб-приложение на C/C++ которое будет быстрее, выше и сильнее чем на PHP в аналогичном режиме (CGI или FastCGI, за моды к Apache или nginx не возьмусь без подготовки), несмотря на 10+ лет отсутствия практики на «Сях». Вот только времени это займет, наверное, на порядок больше (при условии написания и там, и там без использования сторонних либ или, тем более, фреймворков). А могу и на ассемблере (но времени на два порядка больше, и не уверен, что результат будет лучше чем на «Сях» имея в виду интеллектуальность их современных компиляторов). И демонов, в частности, пишу на PHP потому что на нем быстрее писать, пускай и менее эффективно во время выполнения чем на «Сях», но демонов я пишу не ради разгрузки сервера в основном, а для обхода «багофич» PHP в стандартном режиме.
Ну я отталкиваюсь не только от того что на каком то ЯП это работало бы лучше или быстрее. К примеру питон есть из коробки в линуксе, маке и в роутерах на базе линукса, не надо собирать интерпритатор с определёнными флагами, не надо поднимать веб-сервер, не надо выставлять max_execution_time в десяток минут и т.д. Конечно cli у php не просто так дан и можно спокойно и непринуждённо писать консольные приложения/скрипты (что я в общем то и делаю), но порой есть стойкое ощущение что не для этого оно предназначено :)
UFO just landed and posted this here
Я пытался попробовать и руби и питон — мне не нравится синтаксис. Ну то есть может они где-то лучше, красивее (в php название методов и порядок аргументов переодически ошеломляет), но у меня привычка — сиподобный синтаксис.
Мне кажется php-шники потихоньку отходят от cms-ок, нужны только админки, остальное умеет отлично фреймворки.
И первый абзац — можете пояснить на реальных примерах, что такое крутое в питоне, что неудобно в php?
UFO just landed and posted this here
Ясно, в таком случае это правда дело вкуса, a, b = b, a — это синтаксический сахар, и лично для меня совсем не приятный, тк разобраться в этом на порядок сложнее, это показывает ваш первый пример.
И в питоне можно вернуть несколько значений? Только вчера проходил туториал по Go — вынесло немного мозг, впрочем если привыкнуть — действительно удобная фича.
метакласс — это что-то типо шаблонов в плюсах? Но зачем, если не статическая типизиция?
UFO just landed and posted this here
Go ничего общего с Java не имеет. Со Scala наверное путаете :) И Go имеет много общего с динамическими языками, в частности не требует указывать тип переменных (автоматический вывод типа) при объявлении, а в отдельных случаях (для локальных переменных) и самого объявления. Есть «громоздкие» интерфейсы, но используется утиная типизация, то есть в «классе», реализующем интерфейс, на него ссылаться не нужно.
UFO just landed and posted this here
Что-то вы намудрили с алгоритмом евклида =)

def eea(a, b):
return b if a == 0 else eea(b % a, a)

Не заметил, что у вас Расширенный Алгоритм Евклида а не просто gcd
Вы не правы!
Вы писали скорее на «похапэ», а не на PHP.
Параллелизация на Python требует синхронизации ровно также, как и на PHP.
ФП — парадигма, которую «можно» использовать в императивном языке, и PHP ничем не отличается здесь от Python.
Насчет pip, то есть pear, pecl, composer, etc.

Ну и в итоге: все хейтеры PHP, на самом деле на нем никогда не писали и приписывают «мнимые плюсы» другим ЯП!

Или писали очень давно. Хотя, с другой стороны, я тоже «хейтер PHP» и ненавижу его минусы, отсутствие которых я вижу в других, даже едва знакомых ЯП, если не на уровне самого языка, то на уровне стандартных либ или популярных фреймворков. Просто мне это не мешает выбирать его за его плюсы и просто за предсказуемость (лично для меня) его минусов. Это как нелюбимая жена, развод с которой скорее всего повлечет множество проблем (в том числе и финансовых, а не только эстетических или бытовых). Причем за 10+ лет, заметно, что жена PHP изменяется в лучшую сторону :) Пускай и иногда как-то формально, без изюминки :(
UFO just landed and posted this here
Когда я выбирал между Perl и PHP (на то время они были относительно одинаково распространены), то плюсом для меня стала Си-подобность синтаксиса и отсутствие необходимости что-то подключать «внешнее» (по типу #include <*.h> или import) для обработки запроса типа GET /user/volch. Это, конечно, не с чистого листа, но всё же. Хотя сейчас для меня это минусы, а плюсы PHP в другом — прежде всего в более широкой возможности выбора работодателя/заказчика и, как ни странно, в их меньшей разборчивости во многих аспектах, касающихся, скажем так, «экосистемы».
Писать демонов на PHP очень плохая мысль. Я бы рекомендовал это делать на любом другом языке программирования и связывать работу демонов и кода на PHP либо через сетевые сокеты либо через какую то очередь(RabbitMQ, ZeroMQ etc).
Только в виду особенностей реализации интерпретатора. Собственно как язык PHP вполне годится для демонов. Да и начиная с 5.3.2 (кажется) с утечками памяти, прежде всего от циклических ссылок, всё стало намного лучше.
Для каждой задачи есть свой инструмент. Смотря что выполняют демоны. В принципе, я не отрицаю того что можно писать демонов и на PHP, но мое предпочтение относится в этом случае к другим языкам. Это мое личное предпочтение и возможно особенность задач, которые решают демоны.
Довольно много php-проектов написано по принципу:
$app = new Apllication();
$app->processRequest($_REQUEST);
где все инициализации, парсинг конфигов, установления соединений с БД и кэш-серверами и т. п., происходят в конструкторе для каждого запроса. Или аналогично в процедурной форме. Была бы простая и юзабельная возможность из коробки писать демоны с логикой вида
$app =  new Application();
while($app->processRequest($app->getRequest()) { }

где инициализация, происходит только один раз при старте PHP, то для PHP это было бы большим плюсом, сильно повышающим производительность и понижающим необходимость использования других ЯП и/или технологий в проекте.
Ну был тут один товарищ на хабре, написал он phpDaemon — типа нативный fastcgi-сервер на php. Говорят, даже работает (правда, код там немного с душком, но товарищ своей невероятной активностью и кипучей энергией это компенсирует — за что достоин уважения).
Ага, отчасти его имел в виду, когда написал «из коробки» И там не только нативный fastcgi-сервер, но и куча заготовок под различные сервера (от http до даже не знаю чего)
Дмитрий, чем шутить над phpDaemon послушайте лучше:
был тут один товарищ… писал он Realplexor на perl :)
На fastCgi таланта не хватило… Впрочем, говорят, даже работает…

Так что libev и eio наше все… а пишут это на С.
Какой Perl, вы о чем? Дано уже на С++ все написано и в подпапке лежит — кто хочет, собирает и пользуется.
И при чем тут вообще FastCGI? COMET же не пишут на FastCGI…
спасибо, не знал… до сих пор старой версией пользуемся… оценим-с. А FastCGI нужен не COMET'у, он пригодится бы для общения с бэкендом.
У меня был опыт написания мультипроцессного демона с архитектурой подобной apache — мелкий управляющий процесс и куча worker процессов порождаемых основным. Всё это было написано на php 5.2 и zend framework. Демон занимался масштабным сбором и парсингом даннных, обрабатывая сотни тысяч html страниц в сутки и записывая всё в базы данных.

После ряда итераций по стабилизации кода — всё это работало месяцами без перезапуска и не падало.

Так что написать вполне реально и оно даже работает :)
Если бы у Древних Египтян был интернет, пост выглядел бы примерно так:
Рабы строят пирамиды и умирают. Рабы в принципе не надежны. Каждый раз как только рабы возводят новый уровень из каменных блоков, кто-то из них обязательно умирает. А еще их нужно кормить. А если не кормить — тогда умирают еще быстрее. А как вы думаете при таком подходе, построенные пирамиды простоят хотя бы 100 лет? Это же серьезный проект, и использовать для его строительства только рабов не надежно. Вот если бы рабы были демонами, это бы решило проблему. Демона призвал — он работает постоянно, кормить не надо. Вот такой инструмент для строительства пирамид и нужен.
PHP изначально проектировался для stateless серверов для лучшей масштабируемости. При таком подходе действительно не плохая идея забыть о уборке мусора, все равно все освободим одним блоком после короткоживущего запроса. Apache выделяет и освобождает память под запросы большими блоками, что очень быстро. Такой подход позволяет обрабатывать безумное количество запросов (википедия, к примеру).

Нет смысла писать долгоживущие процессы на PHP. Даже со сборщиком мусора можно получить утечки в C-шных расширениях. Apache не расчитан на вебсокеты, он будет использовать память и пул тредов/процессов не эффективно. Это совершенно другой класс задачь, под который нужные другие инструменты. Для очень-быстрого масштабируемого front-end'а PHP подходит очень не плохо.

P.S. мои 2 года PHP, затем 3 года Python/Django (нынешнее время) подсказывают мне, что каждый инструмент имеет свою нишу и один не сильно лучше другого.
Давайте начнем с того, что Personal Home Page разрабатывался он как шаблонизатор. Им (PHP: Hypertext Preprocessor) и он остался.

> stateless серверов для лучшей масштабируемости.

Когда же уже надоест писать про то, что рнр умирает? (: (риторический вопрос)
UFO just landed and posted this here
Ограничения приведены на вполне конкретном языке.
Когда уже надоест минусовать, не вдумываясь ни в комментарий, ни в предмет статьи? (: (риторичнее некуда)
Ага, вижу, что не надоест (:
У нас в проекте куча демонов на PHP, которые крутятся месяцами, и обрабатывают большие объемы строковых данных. Никаких проблем не испытывали. А что бы наверняка, PHP скрипт можно запустить в bash цикле, тогда и исключения, например при перезагрузке MySql не страшны. Правда речь идет о выделенном сервере. Вообще для эффективного использования PHP надо хорошо владеть Линуксом, тогда и такие вещи, как асинхронность выполняеться просто и эффективно, например через pipes. А демоны удобно крутить в screen, всегда можно легко посмотреть вывод.
5 долларов в месяц нет доступа по SSH, утилиты cron или похожего инструмента.
Э… есть. Даже битрикс пашет.
Я делал эти самые большие скрипты о которых говорит автор, работающие сутками в виде демонов с гигабайтами данных на php, prel'e, python'е и сейчас делаю на nodejs.
Конечно при стандартных настройках php сложно добиться стабильности, но если спросить меня, на каком языке получится более стабильный софт то:
1. php
2. perl
3. nodejs
4. python
Самый стабильный в начале или в конце списка?
Удивлен низким местом python. По ощущениям первое-вторые места должен был поделить с php.
С тем что питон хорош, я не спорю, всегда когда требуется работа с комплектующими системы, выбор только в его сторону.
Но в плане стабильности именно софта описанного в статье, я питону не доверяю.
Возможно с альтернативными интерпретаторами ситуация лучше.

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

Возьмем такой примитивный пример, который легко реализовать, напишем на питоне многопоточный парсер хабра, который будет проверять статьи и говорит, если там ваш комментарий.
Допустим мы его реализовали, не особо важно как, запустим на 5, 50, 500 потоках, прогоним пару сотен тестов и посмотрим в результат.
Уверены что результаты будут одинаковые всегда?
Я нет, и мое мнение формируется на основании таких вещей.
> Я не о статье, это просто статья на одну из проблем.
Проблема, которой вы пугаете в этой статье, актуальна для всех интерпретируемых языков.

> Уверены что результаты будут одинаковые всегда?
Естественно нет. Ваша задача сильно зависит от стабильности сети. Она по определению может давать разный результат. Только при чем тут Питон.

> Я нет, и мое мнение формируется на основании таких вещей.
Каких вещей?
Проблема, которой вы пугаете в этой статье, актуальна для всех интерпретируемых языков.

Проблема, которой нас статья пугает, характерна скорее для языков со сборщиками мусора или их аналогами, в общем с языками с автоматически управляемой памятью (или вообще неуправляемой, типа раз (в рантайме) выделилась и вернуть ОС невозможно, но что-то я таких языков не припоминаю, разве что BASIC (не Visual), но и то там был (в некоторых диалектах — точно) REDIM для массивов и, кажется, что-то для скаляров). Интерпретируемые они или нет — не суть в данном контексте. Главное насколько хорошо реализовано автоматическое управление.
> Проблема, которой нас статья пугает,
VolCh, вы уверены, что прочли предыдущие комментарии и верно поняли, о какой статье речь?
Уверен, что прочел, но, видимо, не понял, раз вы спрашиваете :( хотя ту статью и начал читать
То есть у ваших приложений нет обработки ошибок сети?
Я взял работу с сетью как пример который добавляет некий рандом в программу, но который можно нормально обработать.

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

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

> такое встречается не только у меня и нормальных решений нет.
Что встречается? Решений чему?
UFO just landed and posted this here
Там не только это написано.
Первый комментарий звучит как «ну вроде все должно быть хорошо там, сделано для создания серверов и паучков», на деле я не видел не одного веб сервера или паучка на питоне, по крайней мере питоне 2 версии.
Есть альтернативные интерпретаторы, с ними я не работал, о чем уже писал.

Да, не аргумент, но таких вопросов\дискуссий я видел много, когда искал решение.
UFO just landed and posted this here
Это все классно, но разговор про несколько лет назад.
Где то 2008-2009, когда не было такого, может поправили какие то баги в новых версиях 2.6, может просто правильно использовать научились люди.

Напомню что, это лично мое мнение относительно стабильности.
UFO just landed and posted this here
Сейчас уже нет, это было несколько лет и винтов назад.
Но суть одной из проблем, с которой возникают магические штуки, кроется в многопоточности.
UFO just landed and posted this here
Знаю, можете меня в скайпе добавить, онлайн лекцию проведу, если есть сомнения.
UFO just landed and posted this here
А на 5000? Попробуйте.
А лекции это всегда пожалуйста, я только рад буду, люблю пообщаться.
UFO just landed and posted this here
Действительно, какая разница.
UFO just landed and posted this here
Я сразу сказал, что это мое мнение, оно вот так сложилось, и я описал почему, а конкретных примеров я просто напросто уже не помню.
Проблемы могут быть (теоретически) со сборщиком мусора, если каждый тред вызывает его по своему усмотрению.
5000 потоков нагнут ОС, к интерпретатору это не имеет отношения. Если вам нужны 5000 потоков выполнения, пишите на эрланге.
С чего? 5000 потоков успешно работают на пхп, работают на nodejs.
Могу предоставить код, пишите в скайп.
Эммм, каким образом 5000 потоков работают в Node.JS? Он же однопоточный. Может процессов?
Вы передергиваете, уверен что вы прекрасно поняли о чем я.

Хорошо, 5к процессов использующих shared memory и объеденных под управлением главного демона через TCP или UDS.
И пул из 5к веток событий обрабатываемых в единицу времени на nodejs.

PHP+Java+Nginx+HAProxy+MySQL+MongoDB позволяют сделать практически любой проект даже в области high load.
Автор рано хоронит один из наиболее распространенных языков для веб-разработки.
Лучше читать посты перед комментированием. Речь совершенно не об этом.
Почему столько людей вместо того, чтобы заниматься любимым делом, пользуясь любимыми инструментами, тратит время на такие статьи?
Обычно пишут такие статьи для самопиара, есть еще конечно причины, но они не столь сильные, чтобы использовать в этом случае.
Вот не понимаю я, где в статье можно усмотреть негатив в сторону пхп?
Человек просто констатировал факт — пхп рожден чтобы умирать. Всё.
Если бы он написал — «пхп рожден чтобы интерпретироваться», это тоже бы всех возмущало?
Работы по подготовке его к бессмертной жизни начались слишком уж недавно, и еще относительно сыроваты.
Ну да и ладно. Ведь не для того он создан.
Конечно радует что появился gc, ибо иногда бывает нужно использовать пхп за пределами его основного поля деятельности (к примеру когда есть большой проект, и хочется выполнять некие операции в его контексте, и не хочется переписывать базовые библиотеки под другой язык. У меня так и утилиты импорта-экспорта баз данных живут, и даже некоторые системы автоматизации работы 1С на пхп написаны :) ). Но в целом… это не его задачи.
Вы, наверное, ошиблись веткой :)
Если что, я имел в виду, что люди пишут и публикуют статьи, рассказывающие очевидные вещи, сводящиеся к «а вот это PHP не умеет!», «а вот для этого PHP не предназначен!» и т.д. Написали бы лучше как такие задачи решаются правильным способом.
UFO just landed and posted this here
UFO just landed and posted this here
Человек склонен выдумывать проблемы. Взять тот же имитатор cron-а. Во-первых, все меньше хостингов, где нет планировщика, и поддержка его во фреймворках — дань старым временам и ужасным дешевым хостингам (хотя любой такой движок на дешевом хостинге — тот еще ужас). Во-вторых, зачем себе грабли делать с выполнением заданий прямо в коде страницы? Делаем на странице тот же img с src= адресу скрипта, с размером 1х1 точек, который и делаем все фоновые процессы. Не раз в n вызовов, а раз в n минут/секунд/часов/дней. Умер — картинка не загрузилась, никто и не увидел, все равно.

А вообще всегда вспоминаю старую поговорку, что «пилот — это тот, кто может поднять в воздух то, что летает. Хороший пилот поднимет в воздух то, что летать, вообще говорят, не должно». Про кошек и умение их готовить писать не буду, а то уж очень часто автор заметки подчеркивает, что он заслуженный ветеран, и что его мнению можно доверять без оглядки на то, что он мог просто в чем-то для себя не разобраться. )
Глобально я с Вами согласен, но только хотелось бы уточнить, что «имитация крона» это не столько дань старым временам, сколько дань простоте настроек. Даже опытному ветерану иногда бывает лень разбираться где и как в той или иной панельке хостера настраивается крон, а потом еще и проверить что ты все правильно настроил (как проверить кстати? некоторые CMS никаких инструментов для этого не дают).
В общем простота настройки в легких проектах часто перевешивает. А так да, уже почти не осталось хостингов где крона нет как класса.
А зачем брать хостинг, где лень разбираться? Либо разбираться, либо менять хостинг.

Тут получаем неприятный вывод, что тот, кто делает крон из PHP, не позаботившись об обработке ошибок/проблем (т.е. тупо пихает вызов тяжелого фонового задания в основной код страницы на каждый n-ный вывод — как и делает якобы опытный и думающий о последствиях автор-«ветеран»), тот сам дурак. Если же это сделать умеючи, то проблем особых не возникнет.

Знаете, как если бы я в автомобиле колеса напрямик к двигателю, без коробки передач, приделал бы, и жаловался, что «не едет», а про коробку передач и сцепление написал пост, что они — порождение мрака, и я, заслуженный деятель механических наук, который машины видел до их вообще появления на свет, по этой самой страшной причине, ленюсь в них разобраться… Знаете, выражение «старпер», как оно не странно для ИТ-индустрии, само на ум приходит!

Сам не люблю «хостинги с панелями» (особенно сейчас, когда даже VPS с SSD стоят недорого). Многие из таких панелей сделаны «во времена оные», и поддерживаются такими же старперами (либо по старперской «политике безопасности», где основной девиз — «сделай неудобно, не будут пользоваться»), но, если разобраться, все такие панели кладут задания в стандартный cron, а уж он явно лучше справится с обработкой ошибок (ибо отполирован поколениями разработчиков), чем «за-5-минут-на-коленке-написанный» псевдокрон, о котором я начал этот комментарий.
Я не спорю, что крон таки лучше. Я просто уточнил, что есть и другие причины.
Объективно настройка простого скрипта имеет довольно высокий порог вхождения, как это не смешно звучит.
Просто человек который ставит скрипт вовсе не обязан быть даже сильно опытным пользователем.

1 — получи реквизиты доступа
2 — разберись как заливать файлы, и залей их
3 — при необходимости пропиши права на папки
4 — разберись как попасть в базу, и при необходимости залей базу
5 — разберись как скрипту сообщить данные для доступа к базе
6 — найти где прописываюся настройки крон и прописать все настройки
7 — отследить по поведению скрипта что база доступна, что есть возможность сохранять файлы (права папок), что крон запускается…
8 — профит.

Ну сложно же…
Хочется что-то попроще.
Стандарт придумать несложно, а вот его внедрить…
Вы правы, не всегда крон все понятен. Но уж если непонятен, и ему замену писали кривыми руками — пошто тогда на PHP кивать?

Что же касается крона… Мне симпатичнее простой подход: пусть вся тяжелая рутинная логика у нас обслуживается скриптом site.tld/cron.php. Ок, ставим wget этого URL-а в крон раз в столько минут/часов/дней, сколько нам нужно (а проще — раз в минуту, а уже в скрипте смотреть, работать или просто выйти), а на случай отсутствия крона можно через ajax или img src=«URL нашего скрипта» имитировать его запуск.

В скрипте, кстати, разумно, проверять нагрузку сервера, и не запускать задания слишком часто, если нагрузка велика.

Не то чтобы это костыли не напоминает, но мы и говорим с Вами о чем-то простом. Если же у нас проект серьезный, сложный, где настройку сделать не лень, то, может быть, фоновые задания и не лень будет запускать правильно, притом уже станет не столь критично, какой язык для них будет использован.
Пишу на php 5 лет. Прочитал. Автор — редиска.
То что php не годится для демонизации можно написать одной фразой а не рассусоливать смешывая наш любымый язык сами-знаете-с-чем.
90% Прочитанного — какие-то домыслы автора. Он явно не разбирается в вопросе. НЕ хочу чтобы такие глупости публиковались больше на хабре под тихим милым видом «перевод»
И за 5 лет опыта на PHP вы не смогли понять язык, чтобы написать адекватный ответ на его высказывания? Процентами можно раскидываться и в сторону разных бизнесов, пророчить им будущее.
Ждем продолжения:

JavaScript создан чтобы показывать менюшки и попапы
SQL создан чтобы писать сайты визитки
Ruby создан чтобы был конфы для хипстеров куда они могли бы таскать свои макбуки
Python создан чтобы не учить Perl
Java создана чтобы тормозить
C# создан чтобы не учить C++
Haskel создан чтобы потролить
Scala создана чтобы трудоустроить тех кто выучил хаскель.
Lisp создан чтобы все научились закрывать скобочки
Prolog создан чтобы было что в универе преподавать
Visual Basic создан, но не надо.
ObjectiveC создан чтобы хипстеры могли выучить кроме руби ещё что-то.
Dart создан, чтобы быть закрытым в 2018 году вместе с прекращенеим официальной поддержки от гугла.
Вы не поверите, но JS для этого и создан.
Напомнило, на одном местном сайте, торгующем всем для фото, написано под каждым объективом, подходит ли он под съемку свадьбы или нет…
PHP создан чтобы 10 лет писать статьи что этот язык обречен

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

PHP — это самурай :)
Прямо сейчас у меня крутится парсер для map.tiberium-alliances.com/, написанный на, о мой бог, PHP. Жрет гигабайты данных в сутки. Кучка воркеров, кучка менджеров-демонов. Общаются через ZeroMQ. Все сидит в while(true){} уже несколько месяцев после последнего апдйта и почему-то не хочет умирать. Графики всех ресурсов плоские, как грудь моделей. Что я делаю не так?
расширения в конфу добавить забыл.
Очевидно что вам пора менять моделей… :)
Варианты:
— Используете свежий PHP
— Не используете циклические ссылки
— Используете циклические ссылки и вручную их разкольцовываете.
:)
Может у него просто памяти достаточно, чтобы дожидаться заполнения 10к буфера.
Память то на самом деле уже не самое слабое звено.
У меня желание перейти с PHP на более продуманный язык присутствует уже давно, но вот такие фанатичные статьи (с субъективным мнением о недостатках PHP) лишь снижают желание переходить на что-то другое.
Какое же из решений самое простое? Конечно, перенести выполнение заданий из фонового режима в интерактивный! Запускайте их случайно через каждое n-ное посещение страницы (for 1/nth of page visits — ориг.). Тогда случайный посетитель будет тратить свое время на ожидание выполнения общесистемной фоновой задачи, и только после ее завершения личный запрос пользователя будет обработан.

Можно в конце PHP скрипта вызвать ignore_user_abort(true) и послать HTTP заголовок «connection: close», после чего выполнять код общесистемной задачи. В таком случае пользователь ничего ожидать не будет. Плюс, такой метод (без cron, на голом php; описанный в статье, как что-то ужасное) применяется в ситуации ограниченных (или неизвестных) возможностей, например, когда пишется общедоступный скрипт и для простоты его использования конечными пользователями используется минимально возможное кол-во технологий.
PHP это инструмент, не удобно, не пользуйтесь. Зачем устраивать батхерт?
Идиотская статья!

1. Не понятно причем здесь PHP.
100500 ЯП умеют жить в режиме запрос-ответ и это хорошо, а не плохо ( см. горизонтальную масштабируемость )

2. Нет ничего плохого в том, чтобы взять и перезапустить процесс!
Все ЯП текут! Напишите нетривиальный демон на Си, который не течет и я пожму Вам руку!
1. Для PHP это стандартный режим и очень много кода, потенциально повторно используемого, под него заточено, вольно или невольно, с пониманием минусов и без. И это плохо, потому что усиливает необходимость в горизонтальной масштабируемости и/или увеличивает её масштабы :). Иные CMS или фреймворки для инициализации (на каждый запрос!) требуют больше ресурсов, чем собственно обработка типичного запроса. А дефолтный механизм сессий, очень широко используемый, исключает горизонтальную масштабированность тупым балансировщиком. Хотя, конечно, это дело админов чаще, чем непосредственно программистов, но что-то вроде «Я слышал можно хранить твои сессии в Мускуле, а не в через монтирование по NFS — давай, попробуем, а? А то я не знаю что ещё делать.» тоже можно услышать.

2. PHP тёк (подчеркну прошедшее время) неприлично много даже в режиме «родился — ответил на запрос — умер», и это не знания, доступные только гуру, и не баги самого скрипта, а сведения в официальных доках, которые нужно было обходить различными костылями. Синтетический, конечно, пример в доках, но, емнип, ценой максимум десятка процентов производительности, потребление памяти уменьшили при очередном релизе PHP на два порядка. При этом обычного для Си «выделили для тебя память — не забудь её освободить» было недостаточно, нужно было не только освобождать «указатель», но и «ручками» его обнулять.
Дефолтный механизм сессий подменяется с полпинка на любое сетевое хранилище. Redis, memcached, mysql, etc. Дальше уж можно забалансироваться до упаду балансировщиком любого уровня тупости.
Извините, а для каких реальных задач нужно бессмертие?
Запрос-Ответ это же прекрасно.
Хороший пример это тестирование — создание окружение для каждого теста довольно ресурсоемко. Если мы используем фреймворки которые так или иначе кэшируют это окружение, то скорость тестирования возрастает в десятки а то и сотни раз за счет переиспользования инициализации. Так вот — в реальных задачах очень часто происходит примерно так-же: 80% времени уходит на общую часть, и от силы 20% на частное. И да у нас есть мемкэш и т.п., но все равно это не решает всех проблем.
На самом деле это не самое страшное что может быть, просто надо разрабатывать приложение с учетом того, что пхп создан чтобы умирать. И всё :)
Причем могут быть два варианта: разрабатывать, не рассчитывая на бессмертие, или разрабатывать, обходя косяки смертности.
Смертность это не порок, это статистика.
Таким образом, согласен что лучше разрабатывать обходя ее чем ждать пока какой-нибудь WebLogic упадет по неизвестной причине и надо будет его поднимать 15 минут.
Но у php проблема не со смертностью, а с низкой рождаемостью.
Sign up to leave a comment.

Articles