Pull to refresh

Comments 83

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

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


По-моему эта часть неверно переведена, по мне так это ерунда какая-то. Если он имеет ввиду, что в php значения хранятся как универсальный тип и простая инструкция ADD для сложений чисел одного типа не подходит, то тогда это понятно. Однако, всегда есть возможность совершенствовать анализатор для определения типа переменной во время компиляции, например такое повсеместно используется в V8 для javascript и очень успешно. Например счетчик в цикле for часто имеет тип int и это самый простой пример.
в оригинальном тексте именно это и говорится. Качество перевода действительно хромает.
Если он имеет ввиду, что в php значения хранятся как универсальный тип

В разделе «On Objectifying The Standard Library» Энтони так и говорит об этом: «The reason is simple, scalars are not objects, but more importantly they are not any type. PHP relies on a type-system that truly believes that strings are integers.».

Возможно я что-то упускаю…
Если брать конкретно приведенный фрагмент, то там говорится лишь о тех инструкциях, которые будут выполняться на уровне процессора. То есть при реализации функции, складывающей числа, наиболее вероятная ситуация когда мы будем складывать собственно числа, по этому JIT будет генерировать инструкцию add и перед ней ставить проверки на тип аргументов. Если там все же не int, то нужно будет скорректировать статистику и сгенерированный код, и выполнять что-то другое. То есть генерируемый JIT компилятором код адаптируется под те условия, которые есть здесь и сейчас на основе и с учетом вероятности какого-либо события (скажем если в функцию передается string 1 раз из 1000, а все остальное время приходит int, то jit подстраивается и возвращает код оптимизированный именно под int. И наоборот). При текущей реализации у вас есть один код на все кейсы, который по природе своей медленный.

Что до типов и как они хранятся в php — почитайте PHP Internals, так хорошо описан принцип работы zval контейнеров.
Да, над этим пришлось бы очень много и хорошо поработать, однако преимущества не заставили бы себя ждать: от последовательного и более предсказуемого синтаксиса до добавления возможности определять собственный синтаксис средствами самого PHP (представьте себе возможность определять DSL в PHP, которые на самом деле являются частью языка).


А DSL в PHP и так можно определять средствами самого языка, без каких-либо сторонних библиотек: habrahabr.ru/post/186656/ Но проконсультировавшись со специалистами — пришёл к выводу, что это только зла добавит в язык, так что затею бросил =)
Идея неплохая, и метаязыки должны появиться, создатели Zephir ранее заявляли о такой возможности. Есть ещё такая вот реализация. Но использование метаязыка должно давать какие-то плюшки, а пока всё что я вижу — это потеря поддержки IDE.
HHVM — проект с закрытыми исходниками

Разве это так? github.com/facebook/hhvm/
HHVM is an open-source virtual machine...


PHP relies on a type-system that truly believes that strings are integers

Не подскажете, что имеется ввиду? То, что строка — это указатель на нее? Или что-то другое?
По поводу HHVM теперь и у меня самого, хм, вопрос.

Пока искал ответ на ваш второй вопрос, нашел несколько интересных ресурсов на тему внутренностей PHP :)

habrahabr.ru/post/162713/
sheriframadan.com/2012/12/php-oop-objects-under-the-hood/
adobkin.com/blog/categories/development-extensions-to-php/

Да, значение строки хранится в поле char *.
В последнее время в сообществе разработчиков наблюдается весьма оживленное обсуждение всего того, что касается PHP и его будущего. Что радует — большинство подобных разговоров проходят в позитивном ключе.

В позитивном ключе? Автор с Луны? Даже не так… автор с Плутона?

PHP — это ж красная тряпка. Стоит только упомянуть — сразу понабегут рассказывать про фракталы. По моим ощущениям, из всех мейнстримовых языков больше всего ненавидят PHP, потом идут JS и C++… ну Perl ещё. С остальными языками как-то поспокойнее.
«Есть всего два типа языков программирования: те, на которые люди всё время ругаются, и те, которые никто не использует.»
Bjarne Stroustrup.


По личным субъективным наблюдениям последнее время действительно стало спокойнее.
P.S. PHP не является моим основным и тем более любимымы языком, но я рад что он движется вроде бы в правильную сторону.
UFO just landed and posted this here
reactphp + iibevent, и пишите себе в node-style на php. Насколько я помню для php есть экстеншен для асинхронной работы с IO, драйвер для postgresql поддерживает асинхронные запросы… Собственно зачем еще что-то?
UFO just landed and posted this here
Что значит «не рассчитанные»? Ну так используйте те что рассчитаны. На самом деле что синхронная модель в php, что псевдо-асинхронная в node.js, разница не так уж важна. В node.js довольно легко написать так, что асинхронный он, или нет, но тоже может залочиться весь процесс на какое-то время. + как уже упоминалось ниже — callback-hell (да, промисы минимально это дело разруливают но все же).

Словом, я считаю что в своей нише php нормально себе живет и будет жить. А вот попытки переместить php куда-либо дальше web я считаю странными.
UFO just landed and posted this here
Странно вы как-то плавали, т.к. у меня бот висит с 20-го марта этого года — проверяет новые задачи в редмайне и иссью на гитхабе и отправляет в скайп, если появились новые. И до сих пор висит, никому не мешает. Как кушал 5 метров оперативы, так и кушает.

Может на более тяжёлых задачах и проявится что-то, но пока не проявляется почему-то =) Исходники открыты и висят на гитхабе, если интересно — пишите в личку, скину ссылку, сами проверите.
у меня бот висит с 20-го марта этого года

Сейчас «21 апреля 2014 в 12:58» этого года. У вас бот висит минус один месяц?
Тупонул. Март с маем перепутал.
так демон же, однократно запускается… цикл для перезапуска в случае exception'ов
Интереснее вопрос: что в логах? Если он раз в час крашится, то это не показатель отсутствия утечек…
А что, js не течет? в JS сделать что-то что безбожно течет чуть попроще, так что все упирается в ровность рук. Да и сборщик мусора в php не такой уж и плохой.
js не течет? кто такое сказал? одна из главных проблем — сложность детектирования этих утечек, как раз из-за асинхронности и отсутствия стека(события попадают в event loop с чистым стеком)
php в последнее время в этом плане вообще торт :)
UFO just landed and posted this here
забыть var — это не интересно, когда в твоем распоряжении замыкания…
Есть supervisord, и не надо извращений с кроном.

Если не секрет, не припомните какие именно модули у вас ликали?
UFO just landed and posted this here
supervisord как средство избавления от кастылей с pid-ами и кроном.

лики в DPO быстро патчатся, в последний раз у меня проблемы с ним были только на 5.3 версиях.
Ну пока не было крашей. Раньше были, когда гитхаб или редмайн не отвечал, но это поправил, заодно добавил такой вот фикс с готу в батнике, на всякий случай.
Через регистрацию как сервиса. Он же под винду (через COM объект скайпа работает).
Даже на php 4 писались демоны, а на пятом так вообще благодать стала, спокойно работаю месяцами. На ононимках можно даже горячую подгрузку сделать, чтобы не перегружать при новых билдах. Даже mysqli есть, который с базой может асинхронно работать. Есть сборщих мусора и не нужно следить за ссылками как в 4-й версии, а стандартные либы либо не текут, либо быстро патчатся.

А вот мантра не такая бредовая, когда на асинхронных языках начинаешь сражаться с асинхронность, пытаться дебажить, помнить о локах, писать потокобезопасные реализации, убирать мусор и т.д. лучше напищу php код, который будет в 10 раз медленее работать, либо поставлю костыли с pcntl, чем ещё раз на дебаг нодовской библиотеки потрачу времени больше, чем на сам проект.

Никаких кросспоточных проблем в стандартной поставке node не возникает, в том то и фишка, что она однопоточна…
Есть возможность юзать пулл потоков(node-cluster) при необходимости, но это отдельная тема
Отвечу сразу и на пост выше.
Я упоминал не только о ноде, у всех хватает своих тонких моментов. Даже разрабатывая на php в режиме демона нужно о них помнить.
PHP отрабатывает и умирает, подчищая за собой все открытые ресурсы, созданные объекты, глобальные переменные, статик кеши, сбрасывается состояние контейнера, одиночек, подхватывает новый код. Это позволяет не задумываться о таких вещах и избавляет от массы проблем, но бьёт по производительности.
Что угодно можно настроить на работу в режиме FastCGI.
а можно пример веб-сервера для отдачи статики на этом?
(нет, не надо кричать сразу про nginx. некоторые вещи на nginx вы просто не сделаете).
А не могли бы Вы уточнить, о каких вещах в отдаче статики Вы говорите? Для расширения кругозора, так сказать…
например, у вас на диске 30Тб видео, порезанное кусками по 1 минуте. Вам надо отдать 2 часа видео(т.е. склеить 120 сегментов и отдать в рамках 1 http-запроса).
за что Вы порезали видео? Склейте обратно и юзайте streaming
Открою вам секрет: mp4 — это не единственный контейнер для видео.
Ок, вы упомянули модуль streaming, в котором смещение задается в секундах от начала файла, что годится для весьма ограниченного числа применений.

Например, мы делаем облачный сервис видеонаблюдения и клиенту выделяется некое количество Гб/минут записи. Писать видео цельным куском тут не получится(не говоря уже о всяких заморочках с moov atom'ами), да и смещение относительно начала файла теряет смысл.

Так что давайте вернемся к отдаче статики.
На самом деле интересен пример не только на reactphp + libevent, но и на node.js
принципиальной разницы между reactphp + libevent и nodejs нет.
если Вы динамически клеите куски видеофайлов — почему Вы называете это статикой?
по моему мнению, статика это то, что можно отдать напрямую из файловой системы, без модификаций…

в node.js отдача статики реализуется pipelining'ом чтения файловой системы, получается почти как nginx, в reactphp думаю так же.
>если Вы динамически клеите куски видеофайлов — почему Вы называете это статикой?

а в чём проблема? можно mmap'нуть пару файлов и использовать writev() для записи в сокет.
будет тот же самый эффект.

>по моему мнению, статика это то, что можно отдать напрямую из файловой системы, без модификаций…

так оно и отдаётся без модификаций.

>в node.js отдача статики реализуется pipelining'ом чтения файловой системы

а можно всё-таки пример? желательно с sendfile().
Вот сервер для отдачи одного файла…

Пример
require('http').createServer(function(request, response) {
    var filename = require('path').join(__dirname, 'video.mp4');
    var stat = require('fs').statSync(filename);
    response.writeHead(200, {
        'Content-Type': 'video/mp4',
        'Content-Length': stat.size
    });
    require('fs').createReadStream(filename).pipe(response);
}).listen(80);



Писал на память, могут быть ошибки
один — это как раз очевидно и неинтересно. интересно 2 и более :)
да, в одном запросе. чего тут сложного?
Сложного ничего, просто думаю имеет ли смысл тратить на это время…

Пример
require('http').createServer(function(request, response) {
    var files = ['1.mp4', '2.mp4'];

    function nextfile() {
        if (!files.length) return response.end();
        require('fs').createReadStream(__dirname+'/files/' + files.shift())
                     .pipe(response, {end: false})
                     .on("end", nextfile);
    }

    response.writeHead(200, {
        'Content-Type': 'video/mp4'
    });
    nextfile();
}).listen(80);



Не стал считать Content-Size...
Стать асинхронным, как node? Нет, спасибо, не надо нам callback-hell, это путь в никуда. Асинхронным как Akka — да, норм.
прямо так и в никуда…
Кто не хочет, не устраивает себе callback-hell, есть модули типа async, все очень симпатично получается.
Я занимался немного разработкой на node.js и async модуль хорош, но это все равно не позволяет писать код в классическом стиле, лучше смотреть в сторону yield и подобных вещей. Еще я встречал фаната erlang, который рассказывал про ассинхронность у языка в крови и вообще что нет callback-hella и есть более продвинутая система распараллеливания на несколько ядер.

Свою нишу node.js получил на мой взгляд не из-за асинхронности, а из-за популярного языка и легкого старта, легко получить первый работающий результат, низкий порог вхождения.
Может вы и правы, но именно асинхронность стала причиной использования node лично мной на некоторых проектах,
Легкий старт? легче чем в PHP? Не согласен.
Само наличие парадигменного сдвига делает свое дело. Я почти неделю привыкал к тому, что не могу получить результат запроса к базе, как результат вызова функции, но когда освоился, почему-то в сторону yield смотреть не хочется.
Пропало желание подгонять js к некому классическому стилю, я полюбил его таким, какой он есть.
promises — хорошая методология, но иногда и она оказывается излишней.

В основном, кстати я пишу на PHP, так как его средств с лихвой хватает на 90% моих задач.
Превращать PHP в nodejs, разумеется, не нужно, к тому же уже есть reactPHP.
Любопытно, а когда по вашему промисы излишни? И еще — насколько большие проекты вы делаете с применением node.js. Какую часть проекта занимает именно нода? Крутятся ли они в продакшене?
В маленьком API на 10 методов — это ненужная абстракция.
Проектов с node у меня было немного, и все API в чистом виде(для мобильных приложений), без генерации HTML, angular и даже express. Использую restify, хотя можно было бы и без него обойтись.
В продакшне крутятся, но крутятся не у нас, в штатах…
Из них 2 довольно крупные, по реализации около 800rps с одного инстанса, на одном сейчас 3 таких ноды, на втором 2.
Какую часть? Ну собственно rest api, т.е чуть менее, чем полностью(если учитывать хранимые процедуры Lua для Redis).
В маленьком API на 10 методов — это ненужная абстракция.

А какое отношение промисы имеют к абстракциям? Это механизм flow-control, не более. И что вы имеете в виду под «API на 10 методов». Если вы про сам restfull-сервис, то какая разница сколько методов? Если вы про какой-то внутренний сервис, тем более. Сервис может использоваться в каком-то контексте где промисы смогу спасти от callback-hell.
Ну это не совсем control-flow же, async — control flow в чистом виде, а промисы это все же абстракция над control flow.
Наверное, я так рассуждаю, потому что не использовал чужих реализаций, делал свой велосипед, и вот в небольшом сервисе (Сервис коротких ссылок, например, 2 метода, не считая авторизации) я этот велосипед не использую.
Платформа, которая «умеет всё» обречена стать монстром. Уж лучше поднапрячься, изучить дополнительные действительно пригодные для задачи инструменты и внедрить, как дополнение к тому, что уже есть.
Впоне возможно, что более позитивные отзывы связаны не только с обновлениями самого языка, но и с появлением/развитием хороших инструментов, фреймворков, написанных на нем.
Если PHP будет строго следить за обратной совместимостью, то это сильно замедлит внедрение новых возможностей, зато возможно повысит авторитет языка в enterprise-секторе. Подобное мы наблюдаем с таким серьезным промышленным языком, как Java.
PHP, Enterprise… чёрт, а ведь это на яву!
Что-то второй раз замечаю за Anthony Ferrera нехорошую черту — кидать камень в разработчиков Phalcon/Zephir.

Честно говоря, я бы просто выкинул Zephir


Ранее он похожее про Phalcon завялял. Заметьте — сказано абсолютно без аргументации. Почему выкинул? И самое главное ради чего? Чтобы где-то некогда в каком-то светлом будущем построить компилятор из Hack в PECL, хотя Zephir уже умеет компилироваться в PECL расширения! При этом странно хвалить HACK, который работает только на ранее раскритикованной HHVM.
… о которой он почему-то говорит, что она закрытая.

На самом деле, я тоже не разделяю подобную точку зрения. Я пока в данных технологиях не разбираюсь (наверное, поэтому и взялся за перевод), но думаю, что разные подходы важны и полезны. Пройдет некоторое время, а там уж и определятся лидеры и аутсайдеры по различным параметрам, в том числе и по сообществу.
Это конечно очень некрасиво заявлять, что вот чужой труд, на который было потрачено уйма времени и сил, надо просто так выкинуть из-за того что кому-то вдруг понравился hacklang больше чем zephir.
Что угодно придумают, лишь бы не изучать Ruby
Я имею в виду, что PHP был хорош именно своей простотой и доступностью для начинающего. Приближая свой синтаксис к языкам другого предназначения, PHP наступает на те же грабли и может растерять все свои прежние преимущества. When you're hammer, everything looks like a nail.
Для того, что бы не изучать руби — придумали более быстрые языки программирования =)
Ассемблер был до руби, но как-то народ не стремится на нем писать под WEB. Суть новых языков программирования — балансирование на грани между удобством разработки и производительностью. Ну и если вы будете применять язык, который больше склоняется в сторону производительности при реализации задачи, которая требует скорейшего решения, то думаю вам стоит пересмотреть взгляды на выбор инструментов разработки.
Я, как человек не понаслышке работавший с руби — ответственно заявляю, что у руби «балансировка» немного накренилась в сторону просто безумнейших тормозов. Не просто же так гитхаб через раз отвечает заглушкой юникорна или твитч постоянно лагает ;) Не просто же так популярные ресурсы убегают с этого языка на более лёгкие.

Хотя в оправдание могу сказать, что во второй версии скорость немного подняли, хотя работа с json как и была раз в 8-10 медленнее пыха, так и осталась… Ну и добавить лишь то, что это было таким же холиварным ответом к холиварному комментарию =)
Причем тут холивары? Я вообще про это:
$string = "Foo";
var_dump($string->length); // 3
var_dump($string->toLower()); // string(3) "foo"
// etc


Зачем ограничиваться строками? И вот, приходим к понятию: «все есть объект». А если все есть объект, то рано или поздно тормоза обеспечены.

Я свободно пишу как на php, так и на ruby и еще на парочке языков и не буду разводить холивар. Мой месседж не в этом. А в том, что у меня есть набор инструментов (языков, технологий) и я в зависимости от потребностей могу выбирать что лучше под данную конкретную задачу. Если php будет продолжать гнаться за более мощными языками, при этом волоча за собой шлейф обратной совместимости, то может растерять свои декларированные преимущества. Обострится принцип «When you're hammer, everything looks like a nail.», т.е. языки, где все давно есть, в которые надо просто проинвестировать время и изучить, не будут выбираться в пользу php. А php будет балансировать между фичастостью, обратной совместимостью и скоростью. Как результат, боюсь, за всеми тремя кроликами разработчики не угонятся, но все равно удачи им.
«Всё есть объект» в виде кода — не значит, что «всё есть объект» в виде внутреннего представления. Вполне достаточно использовать те же самые операции при обращениям к методам скаляра (с помощью функций) или проверять на скаляр и заменять на аналогичную функцию:

— $string->length на strlen($string);
— $string->toLower() на strtolower($string);
— $string->toLower()->toUpper(); на strtoupper(strtolower($string));

То что внутри рубей это реализовано по другому до такой степени, что пришлось изобретать два разных типа строк (константная — :string и объект — «string») — это проблемы реализации рубей. Если в пыхе требуется поддержка скаляров, как объектов, то помимо возможностей препроцессора внутри самого языка (через кастомные фильтры) есть ещё целое расширение — уже давно nikic это реализовал: github.com/nikic/scalar_objects но почему-то никто особо (особо — это значит как другими пекловскими расширениями, вроде runkit, apc, mcrypt, libevent, intl) этим не пользуется =) Даже hhvm пользуется большей популярностью, имхо.

При этом, сознавая всю красоту ОО подхода к скалярам я придерживаюсь мнения автора поста — это плохо, если разделять методы или свойства к каждому скаляру по отдельности — получим тысячи ошибок вызова методов, просто потому что в переменной в этот момент времени был другой тип переменной. А если делать общие методы для всех типов, то получим ещё большую мешанину, сейчас хотя бы префиксы есть, не везде, но зачастую. Что должно делать "->replace()"? Это аналог array_replace или str_replace? Или может preg_replace? Или суперпопулярная функция substr_replace?
Вы изобрели макросы?
Символ — не строка.
Такие расширения на публичный хостинг никто ставить не будет.
1) Я только изобрёл препроцессор и апи для него, который ставится в виде пакета из композера, а остальная часть за самим языком.

2) Символ из набора символов — не строка, да, логично =) В пыхе, например нет ни символов, ни строк, если уж на то пошло. В пыхе есть только последовательный набор байт, но все называют их строками.

3) Но PDO почему-то ставили, его даже после этого в язык встроили. Mcrypt ставили, ейписи, либэвент, интл, крул, сокеты и многое другое. В чём отличие этого расширения от перечисленных выше?
Эти расширения полезны. То есть без вашего прожить можно, а без интл, курла или мкрипта уже тяжко будет.
Т.е. если подытожить, то максимум что стоит сделать — это:

— Вынести функции в подпространства, по ходу написав соглашение именования аргументов:
str\replace("string", "s", "a"); // atring
// или, на крайний случай
str::replace("string", "s", "a"); // atring

— Добавить множественный импорт из пространств имён:
use str/*;
use array/*;
use str/substr/*;

— Добавить возможность разрешения конфликтов имён классов внутри конечного кода:
use Std\Some\Any;
use Any\Some\Ololo\Any;

new Any; // первый use
new Ololo\Any; // второй use


Остальные модные тенденции превращать всё в объект — фтопку. Опять же, имхо.
В мощных языках для этого используются классы-обертки. Загоняете в такой new MegaString($string) и работаете с методами, расширяете, кстати monkey-patch в php уже можно сделать? Ок, появились traits.

а как вам такое?
use str\replace as str_replace;
use array\replace as array_replace;


и приходим к бесполезности даже начинать пользоваться вашим предложением.

Вернусь к началу. В Java есть базовые типы и классы-обертки. В Scala пошли еще дальше — язык напоминает Ruby синтаксическим сахаром, но базовые типы остались. В Ruby, как и в Smalltalk все есть объект и все интуитивно, но медленно. В php очень простой и неполный ООП и куча функций. Никаких макросов ни в коем случае. Один из проверенных той же джавой подходов — классы-обертки.

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

И часто такой код вы наблюдаете? И почему бесполезности, если несогласованность — это единственный «камень преткновения» на данный момент в пыхе.

На счёт неполного\простого ООП — что имеется ввиду, то что классы — это не объекты или числа? А зачем? Всего должно быть в меру. Возможностей хватает, и если сравнивать с тем же руби — покажите мне позднее статическое связывание на нём, например.

И с чего Вы решили, что Никита или Дмитрий не прочитают этот тред? =)
Да да в PHP очень «неполноценный ООП», что мне интересно там неполноценного-то?
Про «безумные тормоза» это преувеличение. В тех проектах, что участвую и поддерживаю (нагрузки выше среднестатистического сайта) ни разу даже близко не упирались в скорость руби / рельсов.
Хорошо, перефразирую. Скорость руби + рельс. В случае каких-нибудь нитро или синатры — результат будет конечно намного отличаться.
Дело в том, что руби как язык может быть медленнее, но модель его работы другая. Если пхп при каждом запросе заново грузит все классы (хоть и лениво), заново все инициализирует, а в конце умирает, то в руби да и в других языках, 1 запрос = 1 вызову метода, поэтому отдача контента упирается уже в базу или что-то еще, например в медленный шаблонизатор.
Sign up to leave a comment.

Articles