php7 изменения и производительность
30.05.2015Дата выхода php-7.0 все ближе и ближе. Планируемые даты релизов выглядят следующим образом:
- 15 марта 2015 - заморозка функционала
- 11-15 июня 2015 - выход php-7.0-rc
- 15 октября 2015 - выход php-7.0
Рассмотрим что будет из себя будет представлять новый релиз, и стоит ли переходить на php7 в будущем.
Изменения в ядре php7 (zend engine 3, phpng)
Как многие уже знают, самые значительные изменения были проведены в ядре php. Начиная с php-5.0, с каждым релизом, велись работы по улучшению производительности как самого ядра так и OPCache. И производительность действительно улучшалась как в синтетических тестах так и в реальных приложениях. Но к версии 5.5 стало ясно что "узкое место" в плане производительности - это система выделения и освобождения памяти (более подробно об этом можно почитать на php internals). Потому было принято решение переработать типизацию данных, для того чтобы найти оптимальный способ выделения памяти. В течении около пяти месяцев велась работа по рефакторингу и изменению ядра Zend Engine 2.x.
Результаты работы получили кодовое имя phpng, так же известном как "Zend Engine 3". Так как система типизации была изменена - почти все расширения (такие как mysql, ereg и другие) потребовали значительной переработки. Многие из них уже совместимы с phpng, но не все.
Следует учесть, что новое ядро в первую очередь было нацелено на улучшение производительности (и управлением памятью) у "реальных приложений" а не синтетических тестов. И судя по результатам тестов - производительность увеличилась значительно.
Из других преимуществ ядра можно отметить следующее:
- полная поддержка 32bit/64bit платформ
- новый tread-safe механизм
- новый менеджер памяти
- отличная кодовая база для таких вещей как JIT
Недостатки, или следствия изменений:
- размер типов теперь зависит от целевой платформы
В данном релизе внесены значительные изменения в конструкций языка и расширения. Рассмотрим их по отдельности.
Изменения в расширениях
Все расширения были переработаны с учетом новой типизации, но изменения также коснулись и функций.
Итак, наиболее явные изменения:
- Работа с регулярными выражениями (ereg):
- удалены все функции ereg_* (вместо них необходимо использовать preg_*)
- Работа с mysql (mysql):
- удалены все функции mysql_* (необходимо использовать mysqli_* или PDO)
- Множество удаленных функций в расширениях:
- Date
- Curl
- Mcrypt
- Openssl
- json
- dba
- ... список можно продолжить
- Удалена поддержка следующих SAPI (считаются устаревшими):
- apache1
- isapi
- toxen
Новые конструкции и изменения языка
В конструкции языка внесено множество изменений как уровня логики так и простых упрощений. Если говорить прямо, то компилятор php был полностью переписан и на данный момент использует AST для компиляции.
Наиболее очевидные изменения, того что "добавлено":
- возможность обработки исключения, вместо фатальной ошибки
- новые операторы сравнения ( <=>, ?? и другие)
- анонимные классы
- указание типа возвращаемого значения (return type declaration)
- группировка для оператора use
- работа с замыканиями (closure)
- скалярные типы аргументов функции (scalar type hints)
- опционально доступный "строгий режим" работы с типами (stitict mode)
- изменена трактовка переменных и выражений
- улучшена работа с генераторами ( ключевое слово yield from и другие изменения )
- конструктор класса в стиле php4 (когда имя класса совпадает с именем метод) теперь генерирует E_DEPRECATED и будет удален в php8
- изменено поведение побитовых операторов <<, >> и других
- изменено поведение функций funct_get_args и funct_get_arg
- функция языка unserialize принимает дополнительный аргумент
- функция языка list изменила поведение
- изменено поведение цикла foreach (например в работе с внутренним итератором)
- новый синтаксис unicode последовательностей
То что будет "удалено" и более не поддерживается:
- удалена поддержка скрипт. тега в стиле ASP (то есть <% )
- удалены функции call_user_method и call_user_method_array
- удалена переменная $HTTP_RAW_POST_DATA (необходимо использовать потоки)
Рассмотрим некоторые нововведения подробней.
Новые операторы
Оператор use стал немного умней, теперь допускается конструкция с несколькими пространствами имен, к примеру:
Добавлен оператор сравнения с null "??". Он позволяет в некоторых случаях сделать код более читабельней, к примеру:
Добавлен оператор комбинированного сравнения "<=>" (T_SPACESHIP). Его суть заключается в следующем:
- возвращает 0, если оба операнда равны
- возвращает -1, если левый больше правого
- возвращает 1, если правый больше левого
Исключения (exception) на замену фатальным ошибкам (fatal error)
Отличная возможность отловить и обработать ошибочные ситуации, без краха
логики уровня приложения.
Иерархия исключений, для обработки такого рода ошибок, выглядит
следующим образом:
- BaseException
- ParseException
- EngineException
- TypeException
- Exception
- ErrorException
- RuntimeException
Существует возможность обрабатывать такие случаи:
Указание типа возвращаемого значения (return type declaration)
Функции могут декларировать явно тип возвращаемого значения в прототипе (с помощью языковой конструкции). В случае если возвращаемое значение не соответствует заявленному во время выполнения - происходит FatalError.
Также можно отметить, что:
- такие типы как "resource" и "null" не поддерживаются
- в случае не совпадения типов - php пытается их привести, и только в случае неудачи происходит FatalError
Скалярные типы аргументов функции (scalar type hints)
Данная возможность позволяет указать в прототипе функции тип int, bool, string и другие. Тип null и resource не поддерживаются.
Если во время выполнения подобной функции передается не соответствующая типу переменная, компилятор пытается ее преобразовать, и в случае если это не возможно - происходит FatalError.
"строгий режим" работы с типами (stitict mode)
Интерпретатор позволяет регулировать "строгость" соответствия типов данных
с помощью директивы declare(strict_types=1). Данная
директива позволяет включать или выключать строгий режим типов.
Есть несколько особенностей ее использования:
- директива declare - обязана быть первым оператором в файле.
- при включении "строгого режима" ( в начале файла есть оператор declare(strict_types=1) ) - данный режим включается только у того файла где есть эта директива
Пример работы в обычном режиме:
Пример работы в "строгом режиме":
Анонимные классы
Анонимные классы похожи на аналогичные в других языках и на существующие в php5 анонимные функции.
Изменения в интерпретации переменных
В новой версии интерпретация переменный стала следовать семантике left-to-right. Сравним некоторые случаи.
PHP5:
PHP7:
Изменения в некоторых языковых конструкциях
Изменено поведение list(), и именно:
- добавлена возможность распаковки объектов с ArrayAccess
- убрана возможность распаковки строки
Из приведения типов убрано привидение типов из строки "0xXXX" в число.
Убрана возможность повторной декларации переменных в прототипе функции:
Для именования классов, интерфейсов и примесей теперь нельзя использовать имена зарезервированных типов:
Изменено поведение побитовых операторов. Сдвиг int на количество битов большее разрядности int всегда будет возвращать 0.
Побитовый сдвиг на отрицательное число будет возвращать false и генерировать предупреждение.
Выводы
Проделанная разработчиками работа над php7 действительно огромная. Язык начинает приобретать новый, более изящный вид. Да, в этом релизе все еще существует оператор "goto" и наборы функций вроде "array_*", как и много других спорных моментов. Тем не менее, даже с учетом этого, прогресс есть :).
Как и другие major релизы, php7 ломает не мало зависимостей, но с другой стороны дает более совершенный инструмент для разработчика. По результатам тестов (синтетических и на реальных системах) мы получаем (имеются ввиду билд с HHVM):
- прирост производительности в 2 раза (примерно)
- потребление памяти уменьшено на ~ 40% (почти в два раза)
Комментарии