18 заметок с тегом

php7

Позднее Ctrl + ↑

PHP7: scalar hinting

Продолжаю потихоньку наблюдать за развитием ПХП 7. Сегодня с утра выписывал из репозитория и компилировал новую версию, заметил, что в  языке появилось указание типов для скаляров — поддерживаются int, float, string и bool.

Выглядит всё довольно естественно:

<?php
class Test
{
    public function __toString()
    {
        return "test";
    }
}

function len(string $a): int {
    return strlen($a);
}

echo len(new Test);
echo len(new stdClass); // Fatal error: Argument 1 passed to len() must be of the type string, object given

В данном случае первый вызов ошибку не вызовет (в отличие от второго), так как у объекта есть магический метод __toString, который вызывается, когда объект требуется привести к строке, так что всё логично. Возможные преобразования описаны в документации и ничего нового там нет, всё в соответствии с текущей логикой языка.

Есть и второй режим работы — строгий. Его можно включить при помощи конструкции declare, которая должна быть первой конструкцией языка (теперь у неё приоритет даже над namespace) в файле:

<?php
declare(strict_types=1);
namespace Test;

class Test
{
    public function __toString()
    {
        return "test";
    }
}

function len(string $a): int {
    return strlen($a);
}

echo len(new Test); // Fatal error: Argument 1 passed to Test\len() must be of the type string, object given

В этом случае все проверки на тип становятся строгими и никаких неявных преобразований не допускается.

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

PHP7: функции → опкоды

Как известно, в ПХП7 некоторые функции будут заменены на опкоды для ускорения работы. Вызов функции — дорогая операция в этом интерпретаторе, а опкоды — дёшевы. Я заглянул в исходные коды (см. функцию zend_try_compile_special_func, если интересно) и нашёл там список функций, которые заменяются в текущей версии «семёрки».

Это strlen, все функции is_* (is_float, is_string и прочие), defined, call_user_func_array, call_user_func и assert.

PHP7: spaceship operator

В ПХП7 вошёл новый оператор — «космический корабль». Я его помню со времён программирования на Перле. Наиболее частое применение он, по всей видимости, найдёт в сортировках:

usort($data, function ($o1, $o2) {
    return $o1->value <=> $o2->value;
});

Комбинация «меньше», «равно» и «больше» — и есть «космический корабль». Результат его выполнения следующий — если левое меньше, получается «-1», если правое — «1», если значение равны, вернётся ноль. Для строк уже сейчас (с чётвертой версии языка) существует функция strcmp, которая делает то же.

Новый оператор сравнивает даже массивы и объекты, в RFC есть соответствующие примеры:

echo [1, 2, 3] <=> [1, 2, 1]; // 1
echo [1, 2, 3] <=> [1, 2, 4]; // -1

$a = (object) ["a" => "b"];
$b = (object) ["a" => "c"];
echo $a <=> $b; // -1
 
$a = (object) ["a" => "c"];
$b = (object) ["a" => "b"];
echo $a <=> $b; // 1
 
// only values are compared
$a = (object) ["a" => "b"];
$b = (object) ["b" => "b"];
echo $a <=> $b; // 0

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

Производительность PHP 7 на уровне HHVM?

PHP-NG vs HHVM (60.34КиБ)

Если изображённое на графике хоть отчасти правда, то я очень жду выхода ПХП 7 — куда больше, чем нового сезона «Игры Престолов». Автор графика сравнил производительность разных интерпретаторов ПХП на движке «ВордПресс».

По результату видно, что производительность новой версии находится на уровне HHVM!

Значительное отставание HHVM до четвёртого прогона объясняется «прогревом» ДжИТ-компилятора, на это можно не обращать внимание, поскольку основная область применения ПХП — сайты, а на них не заходят только пару раз.

Скорость PHP7 на интерпретаторе Brainfuck

Производительность PHP7 (161.98КиБ)

У меня есть старинная забава — брать свой оптимизирующий интерпретатор языка «Брейнфак» и запускать программу, вычисляющую число «Пи» под разными версиями ПХП, чтобы посмотреть их производительность. Тест довольно синтетический, но посмотреть всё равно интересно.

Сравнил в данном случае версии 5.5.14  и сегодняшнюю сборку 7.0, разница всё равно заметна, хоть и не так впечатляюща, как в случае с «Вордпрессом» — там разница в два раза.

Время у меня на скриншоте общее — то есть трансляция программы на «Брейнфаке» в ПХП и запуск получившегося через eval.

PHP7: строки с Unicode-вхождениями

\u{…} (11.43КиБ)

ПХП тут сделал маленький шаг к унификации синтаксиса с Руби, Джаваскриптом и HHVM — ввёл возможность указывать Юникодные символы через последовательность на скриншоте. Сегодня я выписал текущую версию из репозитория (она, кстати, не компилируется без исправлений в коде) и убедился, что всё работает.

Конструкция «??»

В ПХП 7 появилась, наконец, конструкция, которая должна была быть в языке с первых версий:

echo $_GET['var'] ?? 'default'; // PHP 7
echo isset($_GET['var']) ? $_GET['var'] : 'default'; // PHP 5.6 и ниже

Очень похоже на тернарный оператор без средней части, появившийся в версии 5.3, но с одним отличием: проверяется не ложь или истина, а существование.

Теперь в ПХП можно писать намного более эмоционально:

echo X-D ? :-D ??!! O_o; // это работает в PHP 7, я даже могу сказать что это значит.

Может кому-то пригодится, я собирал у себя на «Маке» текущую версию ПХП 7 при помощи следующих команд:

git clone https://github.com/php/php-src.git
cd php-src

brew install re2c
brew info bison27
PATH=/usr/local/opt/bison27/bin/:$PATH

./buildconf
./configure --prefix=/opt/php-5.7 --disable-all
make
make install