Общие сведения. Увеличиваем потребление памяти вдвое. Увеличиваем потребление памяти втрое. Ещё раз увеличиваем потребление памяти на ровном месте. Заключение. Известно, что PHP активно использует механизм copy-on-write. Это означает, что при попытке внутри функции что-то записать в переданные ей параметры, вначале будет сделана копия этой переменной, а уж затем в неё что-то запишется. Такая же ситуация наблюдается с итерацией массива с помощью foreach. Отсюда следует, что вам потребуется увеличить количество памяти для создания копии переменной и времени (ресурсов ЦП), чтобы всё это проделать. Т.е. возникнет пауза, прежде чем PHP перейдёт к следующей строчке вашей программы. Но прежде чем продолжить дальше по теме, я бы хотел рассказать зачем вообще, что-то передаётся по ссылке, а что-то - по значению. Честно, говоря, я об этом узнал несколько месяцев назад. Т.е. то, что объекты (и массивы, об этом - далее) в PHP всегда передаются по ссылке, а всё остальное по значению - я знал. Но вот зачем - нет. Ответ нашёлся в курсе по Go, как ни странно. Это компромисс. Если умолчать про массивы (и, как заметили в комментариях, строки, которые тоже массивы), то все остальные типы данных в PHP - это скаляры (чтобы быть точным см. is_scalar). Скаляры не занимают много памяти, поэтому их можно быстро скопировать, и передать в функцию копию хранимого значения. При этом на вызывающей стороне значение переменной не изменится. Объекты же могут быть огромными, например DOM-дерево огромного XML-документа. Делать копию такого объекта слишком дорого и по времени и по памяти, поэтому он передаётся по ссылке. Так почему бы не передавать скаляры тоже по ссылке? Дело в том, что передавая что-либо по ссылке мы таким образом теряем контроль над переменными в месте вызова. Представьте себе функцию с кучей параметров: И все они передаются по ссылке. Что случится с локальным контекстом после вызова этой функции? Останутся ли все эти переменные в тех же значениях, что и были до вызова doSmth? Неведомо сие. Всё это остаётся на совести разработчика функции doSmth. Т.о. вы частично или полностью теряете контроль над своей программой. Поэтому и придумали компромисс: скаляры всегда передаём по значению, а объекты - по ссылке. Уточнение, которое, кажется, необходимым сделать, судя по комментариям. В «Основы подсчёта ссылок» есть следующий текст: Так как PHP содержит пользовательские ссылки, которые можно создать оператором &, контейнер zval также содержит внутренний механизм подсчёта ссылок для оптимизации использования памяти.. Это означает, что в PHP есть как ссылки, которые определяет пользователь через амперсанд, так и внутренние ссылки, которые PHP использует где-то там в своих недрах и для своих нужд. Когда в статье говорится о ссылках и передаче по ссылке, то имеется в виду такое поведение, когда копия значения переменной не создаётся. Однако в документации есть строгое определение того, что PHP называет ссылкой и как с этим работать, см. тут, тут и «References Explained». В рамках этой статьи я этому строгому определению не следую. Массивы в PHP передаются по ссылке. Но если вы что-то попытаетесь записать в него, то будет создана копия массива со всеми вытекающими по памяти и процессору. Это и есть реализация механизма copy-on-write. Пример: На моем компе с PHP 8.2.3, кстати, вывод будет таким: Т.е. всего лишь записав нолик в первый элемент массива, мы увеличили потребление памяти вдвое! Это ли не чудо! Array assignment always involves value copying. Use the reference operator to copy an array by reference, см. тут. Что делать с этим? Да, нужно поставить амперсанд перед параметром $array, вот так: function doSmth(array &$array, int $memory). Тогда вывод станет таким: 2680 - 2648 = 32. 32 - это скорее всего кол-во памяти, выделенное на саму переменную $array (но не её значение). Как бы там ни было, это не вдвое. Проблема решена. Сейчас расскажу, как увеличить потребление памяти втрое (да, сам понимаю, что немного странно написана статья: казалось бы нужно рассказывать, как уменьшить потребление памяти, но... так показалось проще объяснить). Затираем амперсанд, возвращаем всё взад и попробуем сделать что-нибудь с массивом, например увеличить на 1 каждый его элемент (всё то же самое, только добавили foreach и break, чтобы не мотать весь массив): Вывод: Как видите, потребляемая память максимальна внутри цикла. Дело в том, что при попытке что-то записать в массив внутри цикла foreach, PHP создаёт (в нашем случае ещё одну) копию массива. И даже если поставить амперсанд перед $value , то это не поможет никак.   foreach вообще достаточно проблемная конструкция для синтаксического сахара. Без проблем её можно использовать только для "посмотреть" на каждой итерации, "сделать" же что-то обходится слишком дорого: О тонкостях работы foreach в PHP Подводный камень в foreach Альтернативой будет использование цикла for.  Обратите внимание, что размер массива должен вычисляться только один раз перед циклом, а не на каждой итерации: По ходу пьесы обнаружил ещё две интересные статьи на Хабре: Сравнение производительности перебора массивов в цикле через for() и foreach(). Так ли это для 8-ой версии не знаю, не проверял. array_* vs foreach или PHP7 vs PHP5. Тест на скорую руку показал, что array_map потребляет тоже почти в 3 раза больше памяти (а без амперсанда перед $array ещё больше).  Таким образом, оптимальным, без всяких дополнительных затрат, будет вариант с передачей массива по ссылке и использованием for.  Ну и сладкое на десерт. В замечательной статье «Массивы в РНР 7: хэш-таблицы» говорится о том, что массив, точнее его внутреннее представление может храниться в упакованном и классическом виде. В упакованном - значит в сжатом. Сжатым массив создаётся, когда в нем используются только целочисленные ключи и только по порядку, например так: Или используя функцию range, как это делалось в коде выше, например: Вывод: Массив начал занимать в 3 раза больше памяти после того, как в него добавили один (один!) элемент. В 3 раза, Карл! На ровном месте. Никто не ждал подвоха, а тут опять и снова! Для других значений (вместо 100) статистика по увеличению потребления памяти выглядит так: Размер массива, шт Кол-во памяти до, байт Кол-во памяти после, байт Разница, раз 10 408 728 1.8 100 2648 8280 3.1 1000 20568 41048 2 10000 266328 655448 2.5 100000 2101360 5242992 2.5 1000000 16781424 41943152 2.5 Таким образом, если вдруг вам захочется добавить в ваш массив какую-то информацию об этом же массиве (например среднее значение или min и max), то не надо. Создайте для этого другой массив или используйте stdClass: Справедливости ради отмечу, что утверждение о том, что целочисленные ключи должны идти строго по порядку - не совсем верно. Они могут идти не по порядку до тех пор, пока значение ключа не превысит размер хэш-таблицы, см. раздел «Конструкция хэш-таблицы». Аккуратно работайте с массивами, особенно с большими. Их точно лучше передавать по ссылке, как PHP передаёт объекты. Используйте for. Думайте, проверяйте и замеряйте. Держите массивы упакованными. Рассмотрите возможность использования SplFixedArray. Тут вообще нужно быть осторожным и проверять всё именно для вашей версии PHP. Работает ли for быстрее foreach на восьмёрке? А на семёрке? А на пятёрке? Т.е. всё то, что написано, верно для моей версии PHP на моём компьютере, но верно ли для вас - вопрос. P. S. Обнаружил ещё одну интересную статью: «Насколько большие массивы (и значения) в PHP? (Подсказка: ОЧЕНЬ БОЛЬШИЕ)». В комментариях, у пользователя @inilim2 показатели потребления памяти оказались в 3 раза выше, чем у меня. Выяснилось, что с версии 8.2 PHP стал потреблять гораздо меньше памяти (по крайней мере для хранения целочисленных массивов). @FanatPHP подсказал инструмент для тестирования кода PHP на разных версиях одновременно. Итого: сколько памяти PHP потребляет на массив из 100 элементов: https://3v4l.org/RK5sK (тут в байтах). сколько памяти PHP потребляет на массив из 100000 элементов: https://3v4l.org/c377f (тут в мегабайтах).  Характер — нордический, стойкий.