Производительность array_merge против объединения в переполнении стека

Я пытаюсь понять как array_merge а также union работать за кулисами в PHP из любопытства.

Может ли кто-нибудь помочь мне понять внутренности ZEND за кулисами:

  • array_merge (медленнее на процессоре и оперативной памяти)
  • UNION (быстрее во всех аспектах)

Вот код теста, который я использую: https://gist.github.com/EnchanterIO/6e90f828c1b32c894d35267c353e83d2

Вывод с использованием PHP 7:

Ray ArrayMerge git: (master) ✗ php src / benchmark.php array_merge 20000

Построение массива из 20000 элементов с использованием array_merge заняло 7 секунд.

Использование памяти составляет: 8 МБ. Пик памяти составил: 12288 МБ.

Ray ArrayMerge git: (master) ✗ php src / benchmark.php union 20000

Создание массива из 20000 элементов с использованием объединения заняло 0 секунд.

Использование памяти составляет: 8 МБ. Пик памяти составил: 10240 МБ.

Моя теория для array_merge:

Я смотрю на PHP исходный код написан на C для объединения массивов (если это даже правильное место) и хотя это немного нечитаемо для меня, так как я не знаком с жаргоном, кажется, что причина, почему array_merge медленнее из-за необходимости дополнительного foreach, а также из-за того, что array_merge перенумеровывает цифровые ключи в результирующем массиве.

Моя теория для UNION:

Не нашел исходного кода для него, но, насколько я знаю, добавление элементов в массив работает так:

  • в начале массив имеет некоторое количество памяти, выделенной внутри
  • добавляя новые элементы в массив, в конечном итоге массиву нужно динамически выделять больше памяти в фоновом режиме, чтобы PHP внутренности (C) создали новый массив с удвоенным объемом памяти и скопировали содержимое
  • добавляя еще больше элементов, этот процесс повторяется
  • нет переупорядочения, нет foreach, просто увеличивается память с течением времени

Может кто-нибудь пролить больше света на процесс и подробно объяснить скрытую магию ZEND?

Обновить:

Меня сослали на следующие ссылки, но я все еще не могу понять, как это сделать:

https://lxr.room11.org/xref/php-src%40master/Zend/zend_opcode.c#740
https://lxr.room11.org/xref/php-src%40master/Zend/zend_operators.c#897
https://lxr.room11.org/xref/php-src%40master/Zend/zend_hash.c#1915

2

Решение

Я полагаю, что мой тест был несправедливым, потому что (надеюсь, никто не имеет здравого смысла) перебирает массив и затем использует array_merge объединить один элемент.

Я создал новый эталонный тест показывая разницу между объединением двух больших массивов в один foreach и ручное добавление и используя array_merge.

введите описание изображения здесь

Результат

Нет преимущества в производительности при объединении двух массивов вручную по сравнению с объединением их с array_merge.

0

Другие решения

Других решений пока нет …