Telegram Web Link
Пых
🔴 PHP-линч #20 Через час линч! https://youtu.be/j7w5nmk2AFE
▶️ Начали!
Please open Telegram to view this post
VIEW IN TELEGRAM
🤵 💍 👰

Сегодня у нас с Ольгой год семейной жизни! А ещё, так совпало, свадьба моего брата! По этому поводу мы записали кавер на любимую песню. Приглашаю вас послушать!

https://youtu.be/nIA4GDz9APE
▶️ PHP-линч #21

К сожалению, в 19 не получается, поэтому проведу на час раньше из кафе. Надеюсь, будет нормально слышно.

https://youtu.be/DxmX2A_WJTk
Please open Telegram to view this post
VIEW IN TELEGRAM
Пых
▶️ PHP-линч #21 К сожалению, в 19 не получается, поэтому проведу на час раньше из кафе. Надеюсь, будет нормально слышно. https://youtu.be/DxmX2A_WJTk
Вчера на линче коснулись нюансов работы автовайринга в Symfony. В какой-то момент я сказал, что даже если в DI найдётся ровно один сервис, реализующий некий интерфейс, то Symfony не заавтовайрит этот сервис без алиаса. Но в чате меня поправили, и я пообещал проверить.

Я был не прав. Действительно, если в контейнере имеется только один сервис, имплементирующий интерфейс, то он без дополнительных телодвижений будет использован для инъекции по этому интерфейсу. И только если таких сервисов 0 или несколько, будет выброшено исключение вида Cannot autowire service "Client": argument "$dependency" of method "__construct()" references interface "Contract" but no such service exists. You should maybe alias this interface to one of these existing services: "Implementation", "AnotherImplementation".

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

$services
->defaults()
->autowire()
->autoconfigure()
->set(Client::class)
->set(Contract::class, Implementation::class)
->args(...);
В PHP 8.4/9 будет новый JIT!

На днях Дмитрий Стогов опубликовал сообщение в externals, в котором представил новый Just-in-Time компилятор (php/src#12079), основанный на собственном фреймворке Дмитрия Intermediate Representation.

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

Изначально Дмитрий собирался оставлять обе версии JIT, но, судя по обсуждению в PR, многие не против просто поменять старую на новую и не париться с поддержкой двух компиляторов. Пока не очень понятно, когда именно всё это выйдет, но я охотно верю, что уже в PHP 8.4 (ноябрь 2024).

Большое спасибо Владимиру Плахотникову за идею для поста!

P.S. Я заболел, поэтому отложил все свои анонсы. Сейчас иду на поправку. Если всё будет хорошо, то в среду мы зарелизим на стриме Typhoon 0.2.0 (бывший PHP Extended Type System) с новой крутой статической рефлексией, а в четверг я опубликую заявку для записи на курс.
🧑‍🏫 Хардкорный курс по PHP, 2-ой поток (2 группы)

Ну что ж, момент настал! Подготовил базовое описание. Там ещё явно не всё есть. Пишите в комментариях, какие вопросы вас интересуют в первую очередь. Ниже продублирую только информацию о том, как попасть на курс.

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

Далее необходимо пройти опрос а-ля "срез знаний" (вспоминаем школу 😅️️), ссылку на него я размещу здесь, на канале Пых, 23 сентября (завтра) в 12:00 по Москве. По результатам среза я сформирую 2 группы по 10 студентов со схожим профилем знаний. При прочих равных приоритет будет отдаваться тем, кто раньше пройдёт опрос.

Желаю удачи!
В PHP есть дженерики!

Меня тут осенило, что тип static в PHP (доступен с версии 8.0) — это, по сути, дженерик. В каждом классе его можно представить как ковариантный параметр-тип с ограничением self, который прокидывается по цепочке наследования, каждый раз уточняясь.

/**
* @template-covariant TStatic of A
*/
abstract class A
{
/**
* @return TStatic
*/
abstract public function returnStatic(): object;
}

/**
* @template-covariant TStatic of B
* @extends A<TStatic>
*/
abstract class B extends A
{
}

Пруф в песочнице Psalm вместо тысячи слов: https://psalm.dev/r/a5eda433d5
Пых
Срез знаний для "Хардкорного курса PHP"! Форма закрыта 25 сентября. Вопросы скоро разберём на стриме. Копия формы для тех, кому просто интересно, что там было: https://forms.gle/zGZ2s7W7VR2nLDBy8.
🥳 Отбор на "Хардкорный курс PHP" завершён

Ну что ж, я наконец-то обработал 200 заявок на курс, и два десятка студентов получили ночью письма с дальнейшими инструкциями. Большое спасибо за такой интерес, мне очень приятно!

Как именно я отбирал, рассказывать не буду. Скажу лишь, что декораторы, правильно описанные словами, принимались. 😊 Ну и как обещал, у всех был одинаковый шанс попасть на курс: я не изучал колонку с email-ами и не добавлял очков тем, кто присылал мне мотивационные письма в личку.

На ближайшем стриме обязательно обсудим вопросы и задачи из формы.
⚓️ Podlodka PHP про тесты!

Вряд ли среди нас найдётся пыхарь, который считает, что тесты вообще не нужны. Здесь всё очевидно. Но вот про само тестирование существует куча холиваров. Верна ли пирамида? Integrated tests are a scam? Класическое или мокистское тестирование? Чистый PHPUnit или дополнительные фреймворки? White box плохо? Нужно ли 100%-ное покрытие или мутационное тестирование? И так далее...

Не знаю, какие из этих вопросов будут затронуты в рамках докладов, но раз собирается знающий народ (Дима Елисеев, ребята из Vi.Tech, Skyeng, SpaceWeb), то обсудить это всё точно получится.

Вот некоторые из заявленных в программе сессий:
• «Как теория тестирования помогает при написании тестов» (Виктор Раев),
• «Как продать автотестирование "бизнесу"» (Виталий Шароватов),
• «Контрактное тестирование (тестирование API)» (Альгис Фатеев),
• «Работа с фреймворками для написания тестов: Codeception» (Евгений Жильцов),
• «Нагрузочное тестирование» (Александр Харченко),
• «Генерация автотестов» (Семен Русин).

https://podlodka.io/phpcrew
Enum и память

Вчера мне стало интересно, в какой момент инстанциируются кейсы enum. При декларации или лениво? Логично второе, но я решил проверить при помощи скрипта:

enum A
{
case X;
}

var_dump(spl_object_id(new stdClass())); // int(1)
var_dump(spl_object_id(A::X)); // int(1)
var_dump(spl_object_id(new stdClass())); // int(2)


Тут видно, что сразу после декларации енама A::X не инстанциировался, так как новому объекту был выдан идентификатор 1. А вот при обращении A::X кейс уже завис в памяти, и следующий объект получил идентификатор 2. Короче, логичное вроде бы верно.

Но что-то мне подсказало перепроверить результат. Для этого я сгенерировал "мегаенам" на 60к кейсов, а затем все их запросил, измерив память до и после (скрипт):

$code = 'enum Mega {';
for ($i = 0; $i < 60_000; ++$i) {
$code .= "case C{$i};";
}
$code .= '}';
eval($code);
unset($code);

var_dump(memory_get_usage() / 1024 / 1024); // 14.9

for ($i = 0; $i < 60_000; ++$i) {
constant("Mega::C{$i}");
}

var_dump(memory_get_usage() / 1024 / 1024); // 13.1 😳

И тут я сильно удивился. Потребление памяти не то что выросло, оно упало!!! Не долго думая, я написал Ilija Tovilo, автору PHP RFC: Enumerations. Вот его ответ:

Enums are generally instantiated when accessed, as you expected. The reason why the memory actually decreases was not obvious to me so I had to take a look. Before enums are instantiated, they have a pseudo-representation. That is, an AST node that contains the name of the enum case and its value if the enum is backed. Once that enum case is instantiated the name and value are copied from the pseudo AST node to the actual object, and the AST node is freed. And it turns out that the AST node actually requires more space than the object itself. If you use opcache this won't be the case, because the AST node is stored in shared memory (assuming you don't use eval), whereas the object lives in "userspace".

Выходит, что кейс enum действительно инстанциируется при обращении. Вот только в этот момент ещё и высвобождается псевдо-AST представление этого кейса, а так как оно тяжелее объекта, потребление памяти сокращается.
2025/07/07 03:30:10
Back to Top
HTML Embed Code: