Определенно, будет полезно на больших наборах данных или в циклах.
Повторю основной принцип:
// Создается новый ассоциативный массив,
// где в качестве ключей получается искомое значение
foreach(array_values($haystack) as $v)
$new_haystack[$v] = 1;
// Теперь можно определить вхождение по ключу
if(isset($haystack[$needle]))
reutrn true;
Как утверждает автор, такой подход ускоряет работу примерно в 280 раз.
Для малых массивов я бы использовать такой обработчик не стал, но вот в каких-либо импортах или обработках данных самое то.
Подобные микрооптимизации существенно усложняют читаемость кода и могут стать причиной неожиданных ошибок. Те несколько (возможно) отыгранных микросекунд никогда не перевесят потенциальный вред от таких трюков.
Кроме того, затрудняюсь представить задачу, при решении которой узким местом станет встроенная функция PHP, а не база данных, или файловая система. Если такая задача действительно возникла, то по-моему стоит задуматься над выбором иного инструмента для ее решения, например, другого языка или специализированной базы данных, вместо насилия над PHP.
Что касается данного конкретного случая, то:
1. Функция in_array и трюк с isset не эквивалентны. Они могут возвращать разные результаты на одних и тех же данных. Это может стать причиной трудных для выявления ошибок. Пример:
2. С введением в PHP новой реализации хеш-таблиц производительность большинства встроенных функций работы с массивами заметно улучшилась, что делает подобные трюки не особенно актуальными.
Иван написал: Подобные микрооптимизации существенно усложняют читаемость кода и могут стать причиной неожиданных ошибок
Читаемость кода не испортится, если организовать всё внутри класса или набора функций, типа MyClass::inArrayEx(); Если сам писал, то проблем с понимаем, что и как работает быть не должно. Тем более, на тестах большинство проблем можно выявить.
Иван написал: Кроме того, затрудняюсь представить задачу, при решении которой узким местом станет встроенная функция PHP
Дело не в функции, а в обработке большого кол-ва данных. Например, импорт данных из файла, по пути импорта данные превращаются в массив и тут начинаются валидации/проверки и прочее, здесь вполне может возникнуть ситуация в миллионы вызовов in_array. В сумме, это вполне может притормозить процесс. Я сравнительные тесты на своих задачах еще не проводил, но как доведется - о результатах напишу.
Иван написал: Функция in_array и трюк с isset не эквивалентны
Не всегда можно быть уверенным в том, на каком железе и ПО клиент будет запускать ваш продукт. Если есть возможность подстраховаться, то лишним это не будет.
Олег Постоев написал: Читаемость кода не испортится, если организовать всё внутри класса или набора функций, типа MyClass::inArrayEx(); Если сам писал, то проблем с понимаем, что и как работает быть не должно. Тем более, на тестах большинство проблем можно выявить.
В том-то и проблема, что если написал сам, да еще и не забыл реализацию. А если другой программист вносит правки в код с таким методом, не зная его реализации, да еще и изменил содержимое массива на подобное тому, что привел Иван, то он рискует получить совсем не то чего ожидал. А раз уж речь идет об обработке большого массива данных, то у программиста есть все шансы не заметить, что его код выдает теперь не те данные, которые он ожидал. Ведь проверить вручную их затруднительно ввиду объема.
Так что я согласен с Иваном. Такой код может использовать разве что для разовой обработки некоего массива данных, когда нужно сократить время обработки с нескольких часов до нескольких минут. Но я бы просто выбрал другой инструмент для этой работы, раз уж она все равно разовая, PHP для такой работы плохо подходит, на мой взгляд.
Экономия не на том...на спичках. Против. Ты подгружаешь ядро битрикса где используют что попало и как легло на душу программисту 1 и программисту 2, пишут двойные кавычки вместо одинарных, что заставляет PHP парсить строку на наличие спец символов и php выражений. А вы тут in_array....
Денис Мальцев, отчасти я с вами согласен. В конечном итоге, конечно, нужно думать как и где использовать такую реализацию, и ни в коем случае не менять все упоминания in_array в коде на isset версию.
Копейка рубль бережёт Нужно действительно смотреть тесты и сравнивать время и результат. Пока этот пост только к сведению, мне идея показалась интересной вот и делюсь. Например, тест с использованием одинарных и двойных кавычек я проводил (давно было). Разница во времени исполнения даже на большом количестве данных была такой несущественной, что больше не обращаю на эти кавычки внимания.
Антон Долганин написал: Парадокс тюнинга на PHP в том, что как только он требуется, реально выгоднее сползти на смежную технологию и не париться
Мне интересно. Можете привести пример из практики, когда вы отказались от реализации на PHP и использовали что-то другое, на что?
Олег Постоев написал: Мне интересно. Можете привести пример из практики, когда вы отказались от реализации на PHP и использовали что-то другое, на что?
Я несколько про другое. Все такие тесты рассматривают пример "переберем 10000 строк" хитровывернутой функцией. Часто ли такая задача всплывает? 10к строк.
Теперь представим, что такая задача всплыла (банальный импорт). Разве мы не перейдем на что-то помощнее в этой задаче? На худой конец, изменим алгоритм.
Я не умаляю эти тесты, не. Просто прикладного применения не вижу
Олег Постоев написал: Мне интересно. Можете привести пример из практики, когда вы отказались от реализации на PHP и использовали что-то другое, на что?
Вопрос был задан не мне, но приведу пару примеров из своего опыта:
1) Стояла задача экспорта в Excel большого объема данных.
Выгрузка 60000 строк с формулами, автофильтрами и форматированием, реализованная с помощью PHPExcel, занимала более 10 минут, причем процессу требовалось несколько ГБ оперативной памяти.
В итоге, вместо PHPExcel был использован Python (библиотека XlsxWriter): скрипт PHP генерировал данные в формате CSV и передавал их скрипту на Python с помощью exec. Время выгрузки сократилось до 15 секунд, память практически не использовалась.
Самое интересное, что реализация на Python заняла меньше времени, чем на PHP, из-за того что XlsxWriter оказался интуитивно понятным и гораздо более предсказуемым, чем PHPExcel.
2) Стояла задача импорта 8 000 000 значений остатков из внешний системы каждые полчаса.
Внешняя система не умела работать в инкрементальном режиме — каждый раз передавались все данные, даже если они не изменились с последнего импорта. Даже после суровой цирковой оптимизации, реализация импорта такого объема данных на PHP занимала больше получаса, то есть, не была рабочей. Кроме того, она сильно нагружала базу данных.
В итоге, было использовано альтернативное решение:
- исходный файл импорта преобразовывался с помощью bash + sed к удобному для MySql виду; - на slave сервере базы данных выполнялся SET SQL_LOG_BIN=0; - далее в рамках того же соединения создавалась таблица; - в таблицу с помощью LOAD DATA INFILE заливались подготовленные данные; - по окончании заливки строился индекс; - выполнялся запрос на сравнение данных между основной и новой таблицами; - на основании запроса генерировались bulk replace запросы к основной таблице, по 100 значений на запрос;
Результатом стало сокращение времени работы импорта до 2-х минут. Нагрузка на Slave базу данных получилась умеренной, на остальные — практически незаметной.
3) Стояла задача реализовать морфологический анализатор для русского языка (часть внутренней системы).
В качестве хранения данных была выбрана структура DAWG, как наиболее оптимальная для решения этой задачи по соотношению сложность/скорость работы. Реализация DAWG графа на чистом PHP с помощью объектов оказалась нерабочей: попытка загрузить словарь в структуру приводил к выпадению скрипта по памяти, не хватало и 10 ГБ.
В итоге, решением стало использование готовой библиотеки для работы с DAWG, написанной на Cи. Сам анализатор был также выполнен на Си в виде FastCGI приложения с предзагруженным словарем. В качестве менеджера процессов использовался spawn-fcgi. Расход памяти на процесс, в итоге, составил менее 4 Мб, а скорость работы просто потрясающей.
Можно вспомнить и другие примеры. PHP — отличный язык, но его область применения — это генерация web страниц. Пытаться решать с его помощью все что только можно — неправильно. Для каждой задачи должен быть свой инструмент. И если для решения проблемы требуется запихать в массив PHP тысячи элементов, то это верный признак того, что инструмент выбран неверно.
Еще пример, где PHP бессилен - боты на сервере. Замена - node.js. Не та замена, про которую кричат на Хабре "node.js это круто", а именно замена по месту - когда необходимо
(выкручиваться с ботами в рамках PHP можно, но до определенного момента, когда банально невыгодно становится)
c помощью проекта peachpie.io который компилит PHP в .NET байткод а как известно Microsoft релизнула .NET на линуксы. так что в скором времен на PHP можно будет писать все что угодно.
Иван написал: ) Стояла задача экспорта в Excel большого объема данных.
может стоило откзааться от этого идиотского формата и использовать экспорт в csv http://php.net/manual/ru/function.fputcsv.php которы можно поточно читать и писать не сжирая гигабайты памяти а парсер вовсе элементарен
скрипт PHP генерировал данные в формате CSV и передавал их скрипту на Python с помощью exec. Время выгрузки сократилось до 15 секунд, память практически не использовалась.
так и произошло) и в итоге питон победил))
PHPExcel - это капец, в нем можно только с xlsx работать, которые по сути xml, а файлы старого экселя махом всю память съедают
Алексей Минеев, просто непонятно зачм питон - если в php из коробки есть работа с csv
xls сам по себе формат не поточный и давно устарел. так что говорим клиенту - покупай памяти достаточно если так нужен формат xls. еще лучше windows и ms office если хотят чтобы файлы были 100% совместимы и без проблем открывалсь.
ну а для тех кто шарит в экономии денег - есть xlsx https://github.com/mk-j/PHP_XLSXWriter поддерживает поточную запись. и не имеет проблем с отжиранием памяти. к тому же не конфилктует с требованием bitrix mbstring.func_overload
к тому же если у вас питон - это яно не шаредхостинг - и по мне так дешевле памяти добавить чем вносить дополнительные затраты в виде разработки и поддержки на питоне.
Группы на сайте создаются не только сотрудниками «1С-Битрикс», но и партнерами компании. Поэтому мнения участников групп могут не совпадать с позицией компании «1С-Битрикс».