Структуры данных в PHP и улучшения в PHP 7, Вы не правильно сравниваете хэши, Russia Laravel Meetup, DevConf 19 июня, Сравнение Golang/Scala/Elixir/Ruby/Python 3 и PHP, Vagrant для PHP 7
Вы слушаете пилотный выпуск «Пятиминутки PHP» — еженедельный подкаст о новостях из мира PHP, интересных постах в блогах и современных подходах к разработке.
Первая новость: «Структуры данных в PHP и улучшения в PHP 7» — интересный доклад с графиками, на сколько быстрее стали различные операции над данными в PHP 7. Как мы знаем, в PHP есть практически универсальный тип array, который может использоваться, и как классический массив с пронумерованными элементами, и как хэш (т.е. ассоциативный массив), и как двунаправленный список, и как стек с помощью функций array_push/array_pop, и как очередь благодаря функциям array_shift или array_unshift. Многие также знают, что есть набор классов Standard PHP Library (SPL). Они предоставляют объектно-ориентированной подход для работы с различными структурами данных, в том числе, там есть настоящие массивы, настоящий стек, очередь, хэш и другие классические структуры.
В этой презентации показаны преимущества и недостатки SPL классов по сравнению с обычным массивом (array). Однако, в PHP 7 была проведена большая работа над тем, как данные хранятся в памяти (известный проект PHPNG), и в итоге обычный тип array во многих случаях стал быстрее и экономнее по памяти, чем SPL классы.
Кстати, продолжая разговор про массивы, недавно на тостере был вопрос, как сделать эффективное пересечение массивов по значению. В PHP есть функция array_intersect, но на большом количестве элементов эта функция тормозит. В упомянутой презентации как раз есть дельный совет: функции array_intersect и in_array действительно работают медленно, т.к. перебирают все элементы массива. Но доступ по ключу, напротив, работает быстро! Поэтому нужные значения можно сделать ключами массива, а в качестве значений массива указать какую-нибудь заглушку, например, true.
В этом случае вместо медленных in_array и array_intersect, можно использовать проверку на наличие внутри массива isset и пересечение по ключам array_intersect_key. В этой связке также не забываем про функцию array_flip, которая меняет ключи и значения местами.
Но тут есть важное замечание, что ключами массива могут быть только числа или строки. Причём, если в качестве ключа попробовать задать строку, содержащую только цифры, она автоматически превратится в число. Учтите это, когда будете записывать ваши бизнес-значения в качестве ключей массива, потому что они могут внезапно превратиться в числа, а потом, при строгом сравнении, вы обнаружите, что что-то не равно чему-то…
Следующая статья на английском, которую можно было бы перевести на Хабр, называется так: «Вы не правильно сравниваете хэши».
Суть проблемы такова. Традиционно пароли в базе принято хранить не открытым текстом, а в форме хэша. Раньше все любили использовать md5 или sha1, позже, в PHP 5.5 появилось специальное API для генерации хэшей паролей. Итак, допустим у нас в базе лежат хэши паролей. Когда пользователь в форме ввода вбивает свой логин и пароль, то на серверной стороне, чтобы понять, правильный ли пароль он указал, мы берём хэш от введённых данных и сравниваем с тем значением, которое лежит базе. Если делать это сравнение с помощью PHP, и делать это не с помощью строгого сравнения (===), а не строгого (==), то некоторых случаях PHP вначале приведёт оба операнда к числу, и только потом запустит сравнение. А именно, если строка начинается с символов 0e, то интерпретатор подумает, что перед ним число в экспоненциальной форме. Ну а поскольку дальше скорее всего идут различные буквы, то обе строки превращаются в нули.
На сайте meetup.com была зарегистрирована группа Russia Laravel Meetup — встречи фанатов, энтузиастов и разработчиков на фреймворке Laravel. На встречах планируется активно обсуждать Laravel и Lumen (напомню, Lumen — это микрофреймворк на базе Laravel), а также экосистему, обмен опытом, ну и конечно-же много фана и неформальной обстановки. Присоединяйтесь, чтобы не пропустить следующую встречу, которая пока не назначена.
Зато уже назначена дата традиционной ежегодной конференции DevConf 2015, которая пройдёт в Москве в гостиничном комплексе Измайлово. Из интересных докладов: Дмитрий Строгов — лидер проекта PHPNG, который я уже упоминал, расскажет про оптимизации в PHP7, а также будут доклады от LinguaLeo про облака, от мамбы про непрерывную интеграцию и от 1С-Битрикс ну вы поняли в общем о чём…
На прошлой неделе я наткнулся на блог-пост
«Сравнение Golang, Scala, Elixir, Ruby и Python 3» на примере следующей задачи: дано несколько текстовых файлов содержащих информацию примерно о 40 миллионах твитов, около 1Гб текста. В этих файлах содержатся локация, автор, текст сообщения, разделённые табуляцией. Нужно посчитать число сообщений, содержащих определённое слово, и сгруппировать их по локациям. По результатам статьи, быстрее всех с этим справились Go и Scala — около 8 секунд. Далее идут Ruby и Python в многопоточном режиме 11 и 13 секунд. Ну а Ruby в однопоточном режиме самый медленный: 45 секунд.
Я решил добавить к этому сравнению PHP! Pull Request уже есть на github. Чтобы сравнить результаты на моём компьютере, мне нужно было взять какой-нибудь тест из оригинальной статьи, я использовал Go, т.к. его проще всего запустить. Итак, Go на моём компьютере показал те же 7-8 секунд, что и в статье. А вот PHP отработал за 11 секунд. Однако, обратите внимание, что программа на Go работала в шесть потоков и загрузила мои ядра на 600%, в то время как PHP работал лишь в один поток, а результат всего в полтора раза медленнее. И да, это был PHP 5.6, надо будет попробовать на новых сборках PHP 7, для которых, кстати, есть отличный Vagrant образ, его можно использовать уже сейчас для тестов ваших проектов на PHP 7.
Подписывайтесь на новые выпуски в RSS или в iTunes и оставляйте комментарии!
не поленился скачал твой код и запустил на маке (со след. конфигурацией: https://www.dropbox.com/s/m65h2g01g1ndbld/Screenshot%202015-05-27%2023.15.31.png?dl=0)
результат: 28.06s user 0.77s system 99% cpu 29.018 total
как у тебя получилось 11 сек ? не понимаю. Я использовал версию 5.6.9
при этом Го (1.4.2) показывает свои 8мь сек.
На той же машине но на php 5.5.20 результаты много лучше: 12.56s user 0.37s system 99% cpu 12.962 total
странно все php собраны через брю, ладно заатра попробую еще другие версии
Интересные результаты, как попробуете другие версии, обязательно расскажите. Интереснее всего, конечно, протестировать PHP 7.
Intel(R) Xeon(R) CPU E5-2620 v2 @ 2.10GHz
php 5.5.14
от 27 до 28 секунд
А если вместо класса Hash использовать массив, то код становится короче, а выполняется скрипт на секунду быстрее
Насчёт класса Hash — это старый трюк, который был актуален во времена 5.3, с ним было на 30% быстрее, чем с массивом.
На PHP 5.6 у меня Hash показал результат на секунду быстрее, чем массив, у вас на 5.5 наоборот… в общем, да, можно уже не заворачиваться с ним.
А я думал, что объект нужен, чтобы нотисы не вылезали при обращении к несуществующему элементу массива)
Кстати, нужно же еще и скорость чтения с винта учитывать. Если тест, найденный на просторах интернета, не врет, то на моей машине чтение 5.7 GB/s. А просто чтение построчно всего файла, без обработки данных, занимает в районе 10 секунд