Pull to refresh

Comments 37

+1. Кстати, именно этот доклад побудил меня перевести эту книгу. Я слушал этот доклад и в зале слышал комментарии типа: «о чем это?», «ничего непонятно». То есть не все PHP-разработчики задумываются о том как работает PHP, а это знание может быть полезным.
Доклад был отличный, это да! А про zval и остальное на русском действительно многим полезно почитать будет, включая меня самого :)
Насчет phpng — я так понял (вполне возможно, что неправильно), что прирост производительности при работе с HashTable будет в каких-то одних случаях, а в других будет что-то вроде fallback к старому варианту и соответственно никакой выгоды. Но я не запомнил, о каких случаях шла речь. Буду рад, если кто подскажет.
Тут вот какой кейс — часто пхп-шный «массив» используется как настоящий массив (как массив в си например), поэтому сделана такая фича:
если HashTable.u.flags | HASH_FLAG_PACKED > 0, значит что элементы массива располагаются просто по порядку (скорее всего он был собран как-нибудь так $ar = []; $ar[] = 1; $ar[] = 42; и т.д.), а значит мы не нуждаемся в хеш таблице как таковой => HashTable.arHash — не инициализирован в данный момент (тут мы экономим память) и если юзер пытается получить доступ к какому-либо элементу, вместо хеширования и лукапа в хеш-таблицу нам надо лишь получить элемент по оффсету (предварительно проверив, конечно, что ключ — не out of bounds), что сэкономит немного времени. Если юзер решит добавить элемент со строковым ключом, или с численным ключом значение которого не равно HashTable.nNextFreeElement — то делаем rehash с убранным флагом HASH_FLAG_PACKED.
Спасибо за замечательное разъяснение! Теперь до меня дошло.
А как только добавили элемент не по порядку, это всё начнёт копироваться в хеш?
И да и нет, на самом деле там несколько условий, проще будет объяснить в коде:

function set($arr, $key, $val)
{
...
if ($arr->flags & HASH_FLAG_PACKED) {
    if ($key < 0) {
        goto convert_to_hash;
    }

    if ($key < $arr->lastUsedKey) {
         if ($arr->data[$key]->type !== TYPE_VAR_UNDEFINED) { // TYPE_VAR_UNDEFINED в данном случае значит что это неинициализированная переменная (ей ничего не присвоили, даже null)
             // добавим этот элемент в массив, он должен нормально туда влезть, заменив какой-то из уже существующих по этому индексу
         } else {
             // если по такому ключу ничего нет (но при этом после него есть ключи, которые мы использовали), то превращаемся в хештаблицу, т.к. только с ней мы сможем соблюсти такой порядок элементов
             goto convert_to_hash;
         }
    } elseif ($key < $arr->tableSize) { // если ключ больше самого большого ключа из этого массива, но меньше чем кол-во заранее инициализированных бакетов (это число всегда кратно 2)
        // просто добавим этот элемент сюда
    } elseif ($key < $arr->tableSize * 2 && $arr->tableSize - $arr->lastUsedKey < $arr->tableSize / 2) { // если ключ больше чем кол-во преинициализированных бакетов, но меньше чем это же число умноженное на два, и при этом если мы уже используем больше половины бакетов
        // инициализировать в два раза больше бакетов чем есть сейчас, и переместить туда их
        // добавить элемент
    } else {
        goto convert_to_hash;
    }
}
convert_to_hash:
...
}


Вроде ничего не забыл, в общем-то это выжимка из этого кода, почитайте лучше его, если закомы с си и пхп на том уровне.
Ага, спасибо! Почитаю. Меня этот момент беспокоит, на самом деле. Так как неожиданно скорость вставки одного элемента может резко упасть.
Да доклад был замечательный. Жаль видео записи нет. А по поводу того что не все PHP-разработчики задумываются о том как работает PHP можно даже по другому сказать( более эпичнее что ли ), Не более 10-20 процентов знают что такое Zend Engine, и не более 5 процентов знают что такое zval, а уж про то сколько всего разработчиков понимают как оно работает и вовсе молчу. я сам грешен буквально пару лет назад из 6 лет работы с php узнал что такое zval и как он работает. И более чем уверен что у меня ещё есть прорехи в знаниях. Кстати может кто нибудь сам записывал доклад на видео? А то похоже от организаторов не дождёмся. Там даже презентации не все есть.

Кстати rrromka приведённый в начале пример не имеет никакого отношения к Zval.
Кстати rrromka приведённый в начале пример не имеет никакого отношения к Zval.

Почему? Я этим примером хотел показать, что функция f1 меняет тип переданного zval-а, по этому внутри неё срабатывает copy-on-write и объект снаружи функции остается без изменения. Функция f2 тип не меняет, по этому копироания-при-записи нет и меняется zval снаружи функции.
Начнём с того что наверное для меня такое поведение очевидно даже без знания Zval.

А далее причём тут вообще тип?
Я согласен с тем, что программируя на PHP можно обойтись без знания о том что такое zval. Но если вы хотите разобраться почему именно в приведенном примере функции f1 и f2 ведут себя по разному, то понимать структуру zval и zvalue_value нужно.

Отличие между этими двумя функциями на уровне zval-ов заключается в том, что первая меняет lval и type переданного объекта, что вызывает copy-on-write. Вторая не трогает lval и type, а работает только с zend_object_value.

Как бы вы объяснили разницу в работе этих функций без упоминания zval-ов?
Ну это понятно из док. Обе функции принимают значения. Но объекты — это ссылочный тип (тип значения). Так что в первой вы меняете переменную (меняете ее значение) в другом скоупе, поэтому она и не изменяется в глобальном. А во второй функции вы работаете с самим объектом (значением аргумента), который является ссылкой. Как-то запутанно это объяснять, но по-моему это не пересекается со знаниями о том, как это устроено внутри.
Ага, только в следующей версии внутреннея структура уже будет другой.
А зачем вешать специфическую статью про PHP в общий хаб «Программирование»?
Непонятная логика. Следуя ей статьи про Java, C++, Haskell и другие языки тоже не нужно в этот хаб вешать.
Ключевое слово здесь «специфическую».

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

С уважением.
Именно. Вывешивание узконаправленных статей в общие хабы ломает систему фильтрации. Я например подписан на хабы языков, которые мне интересны плюс на хаб «программирование» по общепрограммисткой тематике. Если все статьи вешать и туда и туда, то не будет способа отфильтровать интересующий вас контент.
Ещё года два назад на собеседованиях любили спрашивать: «Какова алгоритмическая сложность (в О-нотации) функции strlen($s) в PHP»

Надеюсь, прочитавшие эту статью сразу смогут ответить на этот вопрос.
А что (вопрошающие) считали правильным ответом? O(N) или O(1)?
Вопрошающие знали ответ O(1), но я не уверен в том, что все знали почему.

В одной компании раскритиковали мой ответ: \Theta(1).
Для того, чтобы предположить правильный ответ на этот вопрос, мне достаточно знать, что в строке может содержаться нулевой байт. Если это так, то в большинстве случаев строка состоит из пары (указатель на начало строки, длина строки). Для людей, пишущих на C, причины именно такого решения понятны.

Правда, если вы предположите такое в отношении zsh (а там ноль может быть внутри строки, если только вы не запретили ему там быть с помощью настроек), то вы прогадаете, но других языков, использующих для хранения бинарных строк экранирование я просто не знаю.
Я ответ определил сразу и не вижу никаких причин по которым он может быть иным.
При этом с тонкостями zval не знаком и не вижу, как они связаны с этим примером.
Плюсую, потому что эти вещи довольно чётко описаны в руководстве по языку и для их понимания о внутренностях знать не обязательно.
Зато вопрос в комментарии выше вы не определите без знания внутренностей. А это знание довольно полезно.
А его не надо определять, можно просто помнить.
Это подход кодера, а не программиста. Это как математик, который не помнит формул, но может их всегда вывести.
Кажется наоборот, который помнит, но не понимает откуда эти формулы.
Ну то есть, вы мне сейчас сможете рассказать, начиная с физических принципов, как это всё хранится, какое значение имеет выравнивание, как данные могут оказаться в свопе, как работает DMA в защищённом режиме и так далее?

Я, кстати, это рассказать смогу. Но как устроен zval мне не интересно.
Не так давно на Хабре была статья про неумение сборщика мусора работать с циклическими ссылками. Я так понимаю, это исправили начиная с какой-то версии?
С выхода 5.3, где это исправили, прошло 5 (!) лет. Ничего себе «не так давно».
Если у меня еще раз кто-нибудь спросит, почему я не люблю php, я просто покажу первый пример кода из этой статьи.
В других языках, наверняка, нюансов не меньше. Их надо знать, а лучше понимать. И PHP тут не причем.
UFO just landed and posted this here
Если кому интересна данная тема, то есть хорошая книжка (с переводом на русский) «Профессиональное программирование на PHP» Джордж Шлосснейгл. Часть материала — как раз по начинке php.
Sign up to leave a comment.

Articles