Как стать автором
Обновить

PHP. Как увеличить потребление памяти в 3 и более раз при работе с массивами

Уровень сложностиСредний
Время на прочтение12 мин
Количество просмотров18K

Содержание

  1. Общие сведения.

  2. Увеличиваем потребление памяти вдвое.

  3. Увеличиваем потребление памяти втрое.

  4. Ещё раз увеличиваем потребление памяти на ровном месте.

  5. Заключение.

Общие сведения

Известно, что PHP активно использует механизм copy-on-write. Это означает, что при попытке внутри функции что-то записать в переданные ей параметры, вначале будет сделана копия этой переменной, а уж затем в неё что-то запишется. Такая же ситуация наблюдается с итерацией массива с помощью foreach. Отсюда следует, что вам потребуется увеличить количество памяти для создания копии переменной и времени (ресурсов ЦП), чтобы всё это проделать. Т.е. возникнет пауза, прежде чем PHP перейдёт к следующей строчке вашей программы.

Но прежде чем продолжить дальше по теме, я бы хотел рассказать зачем вообще, что-то передаётся по ссылке, а что-то - по значению. Честно, говоря, я об этом узнал несколько месяцев назад. Т.е. то, что объекты (и массивы, об этом - далее) в PHP всегда передаются по ссылке, а всё остальное по значению - я знал. Но вот зачем - нет. Ответ нашёлся в курсе по Go, как ни странно. Это компромисс. Если умолчать про массивы (и, как заметили в комментариях, строки, которые тоже массивы), то все остальные типы данных в PHP - это скаляры (чтобы быть точным см. is_scalar). Скаляры не занимают много памяти, поэтому их можно быстро скопировать, и передать в функцию копию хранимого значения. При этом на вызывающей стороне значение переменной не изменится. Объекты же могут быть огромными, например DOM-дерево огромного XML-документа. Делать копию такого объекта слишком дорого и по времени и по памяти, поэтому он передаётся по ссылке. Так почему бы не передавать скаляры тоже по ссылке? Дело в том, что передавая что-либо по ссылке мы таким образом теряем контроль над переменными в месте вызова. Представьте себе функцию с кучей параметров:

function doSmth($x1, $y2, $scale, $pojection, $alpha, $type, $reference, $mode): float;

И все они передаются по ссылке. Что случится с локальным контекстом после вызова этой функции? Останутся ли все эти переменные в тех же значениях, что и были до вызова doSmth? Неведомо сие. Всё это остаётся на совести разработчика функции doSmth. Т.о. вы частично или полностью теряете контроль над своей программой. Поэтому и придумали компромисс: скаляры всегда передаём по значению, а объекты - по ссылке.

Уточнение, которое, кажется, необходимым сделать, судя по комментариям. В «Основы подсчёта ссылок» есть следующий текст:

Так как PHP содержит пользовательские ссылки, которые можно создать оператором &, контейнер zval также содержит внутренний механизм подсчёта ссылок для оптимизации использования памяти..

Это означает, что в PHP есть как ссылки, которые определяет пользователь через амперсанд, так и внутренние ссылки, которые PHP использует где-то там в своих недрах и для своих нужд. Когда в статье говорится о ссылках и передаче по ссылке, то имеется в виду такое поведение, когда копия значения переменной не создаётся.

Две разные переменные из разных областей видимости ссылаются на один и тоже объект в памяти
Две разные переменные из разных областей видимости ссылаются на один и тоже объект в памяти

Однако в документации есть строгое определение того, что PHP называет ссылкой и как с этим работать, см. тут, тут и «References Explained». В рамках этой статьи я этому строгому определению не следую.

Увеличиваем потребление памяти вдвое

Массивы в PHP передаются по ссылке. Но если вы что-то попытаетесь записать в него, то будет создана копия массива со всеми вытекающими по памяти и процессору. Это и есть реализация механизма copy-on-write. Пример:

<?php

function doSmth(array $array, int $memory) {

  printf('memory: %s%s', memory_get_usage() - $memory, PHP_EOL);
  $array[0] = 0;
  printf('memory: %s%s', memory_get_usage() - $memory, PHP_EOL);
}

$memory = memory_get_usage();
$array = range(1, 100);
doSmth($array, $memory);

На моем компе с PHP 8.2.3, кстати, вывод будет таким:

memory: 2616
memory: 5264

Т.е. всего лишь записав нолик в первый элемент массива, мы увеличили потребление памяти вдвое! Это ли не чудо! Array assignment always involves value copying. Use the reference operator to copy an array by reference, см. тут. Что делать с этим? Да, нужно поставить амперсанд перед параметром $array, вот так: function doSmth(array &$array, int $memory). Тогда вывод станет таким:

memory: 2648
memory: 2680

2680 - 2648 = 32. 32 - это скорее всего кол-во памяти, выделенное на саму переменную $array (но не её значение). Как бы там ни было, это не вдвое. Проблема решена. Сейчас расскажу, как увеличить потребление памяти втрое (да, сам понимаю, что немного странно написана статья: казалось бы нужно рассказывать, как уменьшить потребление памяти, но... так показалось проще объяснить).

Увеличиваем потребление памяти втрое

Затираем амперсанд, возвращаем всё взад и попробуем сделать что-нибудь с массивом, например увеличить на 1 каждый его элемент (всё то же самое, только добавили foreach и break, чтобы не мотать весь массив):

<?php

function doSmth(array $array, int $memory) {

  printf('memory: %s%s', memory_get_usage() - $memory, PHP_EOL);
  $array[0] = 0;
  printf('memory: %s%s', memory_get_usage() - $memory, PHP_EOL);

  foreach ($array as $i => $value) {
    $array[$i] ++;
    printf('memory: %s, i: %s%s', memory_get_usage() - $memory, $i, PHP_EOL);
    break;
  }

  printf('memory: %s%s', memory_get_usage() - $memory, PHP_EOL);
}

$memory = memory_get_usage();
$array = range(1, 100);
doSmth($array, $memory);
printf('memory: %s%s', memory_get_usage() - $memory, PHP_EOL);

Вывод:

memory: 2616
memory: 5264
memory: 7880, i: 0
memory: 5264
memory: 2648

Как видите, потребляемая память максимальна внутри цикла. Дело в том, что при попытке что-то записать в массив внутри цикла foreach, PHP создаёт (в нашем случае ещё одну) копию массива. И даже если поставить амперсанд перед $value , то это не поможет никак.

Полный вывод работы скрипта без break и с амперсандом перед $value
<?php

function doSmth(array $array, int $memory) {

  printf('memory: %s%s', memory_get_usage() - $memory, PHP_EOL);
  $array[0] = 0;
  printf('memory: %s%s', memory_get_usage() - $memory, PHP_EOL);

  foreach ($array as $i => &$value) {
    // $array[$i] ++;
    $value ++;
    printf('memory: %s, i: %s%s', memory_get_usage() - $memory, $i, PHP_EOL);
    // break;
  }

  printf('memory: %s%s', memory_get_usage() - $memory, PHP_EOL);
}

$memory = memory_get_usage();
$array = range(0, 99);
doSmth($array, $memory);
printf('memory: %s%s', memory_get_usage() - $memory, PHP_EOL);
memory: 2616
memory: 5264
memory: 5328, i: 0
memory: 5360, i: 1
memory: 5392, i: 2
memory: 5424, i: 3
memory: 5456, i: 4
memory: 5488, i: 5
memory: 5520, i: 6
memory: 5552, i: 7
memory: 5584, i: 8
memory: 5616, i: 9
memory: 5648, i: 10
memory: 5680, i: 11
memory: 5712, i: 12
memory: 5744, i: 13
memory: 5776, i: 14
memory: 5808, i: 15
memory: 5840, i: 16
memory: 5872, i: 17
memory: 5904, i: 18
memory: 5936, i: 19
memory: 5968, i: 20
memory: 6000, i: 21
memory: 6032, i: 22
memory: 6064, i: 23
memory: 6096, i: 24
memory: 6128, i: 25
memory: 6160, i: 26
memory: 6192, i: 27
memory: 6224, i: 28
memory: 6256, i: 29
memory: 6288, i: 30
memory: 6320, i: 31
memory: 6352, i: 32
memory: 6384, i: 33
memory: 6416, i: 34
memory: 6448, i: 35
memory: 6480, i: 36
memory: 6512, i: 37
memory: 6544, i: 38
memory: 6576, i: 39
memory: 6608, i: 40
memory: 6640, i: 41
memory: 6672, i: 42
memory: 6704, i: 43
memory: 6736, i: 44
memory: 6768, i: 45
memory: 6800, i: 46
memory: 6832, i: 47
memory: 6864, i: 48
memory: 6896, i: 49
memory: 6928, i: 50
memory: 6960, i: 51
memory: 6992, i: 52
memory: 7024, i: 53
memory: 7056, i: 54
memory: 7088, i: 55
memory: 7120, i: 56
memory: 7152, i: 57
memory: 7184, i: 58
memory: 7216, i: 59
memory: 7248, i: 60
memory: 7280, i: 61
memory: 7312, i: 62
memory: 7344, i: 63
memory: 7376, i: 64
memory: 7408, i: 65
memory: 7440, i: 66
memory: 7472, i: 67
memory: 7504, i: 68
memory: 7536, i: 69
memory: 7568, i: 70
memory: 7600, i: 71
memory: 7632, i: 72
memory: 7664, i: 73
memory: 7696, i: 74
memory: 7728, i: 75
memory: 7760, i: 76
memory: 7792, i: 77
memory: 7824, i: 78
memory: 7856, i: 79
memory: 7888, i: 80
memory: 7920, i: 81
memory: 7952, i: 82
memory: 7984, i: 83
memory: 8016, i: 84
memory: 8048, i: 85
memory: 8080, i: 86
memory: 8112, i: 87
memory: 8144, i: 88
memory: 8176, i: 89
memory: 8208, i: 90
memory: 8240, i: 91
memory: 8272, i: 92
memory: 8304, i: 93
memory: 8336, i: 94
memory: 8368, i: 95
memory: 8400, i: 96
memory: 8432, i: 97
memory: 8464, i: 98
memory: 8496, i: 99
memory: 8496
memory: 2648

foreach вообще достаточно проблемная конструкция для синтаксического сахара. Без проблем её можно использовать только для "посмотреть" на каждой итерации, "сделать" же что-то обходится слишком дорого:

Альтернативой будет использование цикла for.

Hidden text
<?php

function doSmth(array $array, int $memory) {

  printf('memory: %s%s', memory_get_usage() - $memory, PHP_EOL);
  $array[0] = 0;
  printf('memory: %s%s', memory_get_usage() - $memory, PHP_EOL);

  $count = count($array);
  for ($i = 0; $i < $count; $i ++) {
    $array[$i] = 100;
    printf('memory: %s, i: %s%s', memory_get_usage() - $memory, $i, PHP_EOL);
  }

  printf('memory: %s%s', memory_get_usage() - $memory, PHP_EOL);
}

$memory = memory_get_usage();
$array = range(0, 99);
doSmth($array, $memory);
printf('memory: %s%s', memory_get_usage() - $memory, PHP_EOL);
memory: 2616
memory: 5264
memory: 5264, i: 0
memory: 5264, i: 1
memory: 5264, i: 2
memory: 5264, i: 3
memory: 5264, i: 4
memory: 5264, i: 5
memory: 5264, i: 6
memory: 5264, i: 7
memory: 5264, i: 8
memory: 5264, i: 9
memory: 5264, i: 10
memory: 5264, i: 11
memory: 5264, i: 12
memory: 5264, i: 13
memory: 5264, i: 14
memory: 5264, i: 15
memory: 5264, i: 16
memory: 5264, i: 17
memory: 5264, i: 18
memory: 5264, i: 19
memory: 5264, i: 20
memory: 5264, i: 21
memory: 5264, i: 22
memory: 5264, i: 23
memory: 5264, i: 24
memory: 5264, i: 25
memory: 5264, i: 26
memory: 5264, i: 27
memory: 5264, i: 28
memory: 5264, i: 29
memory: 5264, i: 30
memory: 5264, i: 31
memory: 5264, i: 32
memory: 5264, i: 33
memory: 5264, i: 34
memory: 5264, i: 35
memory: 5264, i: 36
memory: 5264, i: 37
memory: 5264, i: 38
memory: 5264, i: 39
memory: 5264, i: 40
memory: 5264, i: 41
memory: 5264, i: 42
memory: 5264, i: 43
memory: 5264, i: 44
memory: 5264, i: 45
memory: 5264, i: 46
memory: 5264, i: 47
memory: 5264, i: 48
memory: 5264, i: 49
memory: 5264, i: 50
memory: 5264, i: 51
memory: 5264, i: 52
memory: 5264, i: 53
memory: 5264, i: 54
memory: 5264, i: 55
memory: 5264, i: 56
memory: 5264, i: 57
memory: 5264, i: 58
memory: 5264, i: 59
memory: 5264, i: 60
memory: 5264, i: 61
memory: 5264, i: 62
memory: 5264, i: 63
memory: 5264, i: 64
memory: 5264, i: 65
memory: 5264, i: 66
memory: 5264, i: 67
memory: 5264, i: 68
memory: 5264, i: 69
memory: 5264, i: 70
memory: 5264, i: 71
memory: 5264, i: 72
memory: 5264, i: 73
memory: 5264, i: 74
memory: 5264, i: 75
memory: 5264, i: 76
memory: 5264, i: 77
memory: 5264, i: 78
memory: 5264, i: 79
memory: 5264, i: 80
memory: 5264, i: 81
memory: 5264, i: 82
memory: 5264, i: 83
memory: 5264, i: 84
memory: 5264, i: 85
memory: 5264, i: 86
memory: 5264, i: 87
memory: 5264, i: 88
memory: 5264, i: 89
memory: 5264, i: 90
memory: 5264, i: 91
memory: 5264, i: 92
memory: 5264, i: 93
memory: 5264, i: 94
memory: 5264, i: 95
memory: 5264, i: 96
memory: 5264, i: 97
memory: 5264, i: 98
memory: 5264, i: 99
memory: 5264
memory: 2648

Обратите внимание, что размер массива должен вычисляться только один раз перед циклом, а не на каждой итерации:

for ($i = 0; $i < count($array); $i ++)

По ходу пьесы обнаружил ещё две интересные статьи на Хабре:

  1. Сравнение производительности перебора массивов в цикле через for() и foreach(). Так ли это для 8-ой версии не знаю, не проверял.

  2. array_* vs foreach или PHP7 vs PHP5. Тест на скорую руку показал, что array_map потребляет тоже почти в 3 раза больше памяти (а без амперсанда перед $array ещё больше).

Использование array_map
<?php

function doSmth(array &$array, int $memory) {

  printf('memory: %s%s', memory_get_usage() - $memory, PHP_EOL);
  $array[0] = 0;
  printf('memory: %s%s', memory_get_usage() - $memory, PHP_EOL);

  // foreach ($array as $i => &$value) {
  //   // $array[$i] ++;
  //   $value ++;
  //   printf('memory: %s, i: %s%s', memory_get_usage() - $memory, $i, PHP_EOL);
  //   // break;
  // }

  // $count = count($array);
  // for ($i = 0; $i < $count; $i ++) {
  //   $array[$i] = 100;
  //   printf('memory: %s, i: %s%s', memory_get_usage() - $memory, $i, PHP_EOL);
  // }

  array_map(function($value) use ($memory) {
    $value ++;
    printf('memory: %s, i: %s%s', memory_get_usage() - $memory, $value, PHP_EOL);
  }, $array);

  printf('memory: %s%s', memory_get_usage() - $memory, PHP_EOL);
}

$memory = memory_get_usage();
$array = range(0, 99);
doSmth($array, $memory);
printf('memory: %s%s', memory_get_usage() - $memory, PHP_EOL);
memory: 2648
memory: 2680
memory: 6160, i: 1
memory: 6160, i: 2
memory: 6160, i: 3
memory: 6160, i: 4
memory: 6160, i: 5
memory: 6160, i: 6
memory: 6160, i: 7
memory: 6160, i: 8
memory: 6160, i: 9
memory: 6160, i: 10
memory: 6160, i: 11
memory: 6160, i: 12
memory: 6160, i: 13
memory: 6160, i: 14
memory: 6160, i: 15
memory: 6160, i: 16
memory: 6160, i: 17
memory: 6160, i: 18
memory: 6160, i: 19
memory: 6160, i: 20
memory: 6160, i: 21
memory: 6160, i: 22
memory: 6160, i: 23
memory: 6160, i: 24
memory: 6160, i: 25
memory: 6160, i: 26
memory: 6160, i: 27
memory: 6160, i: 28
memory: 6160, i: 29
memory: 6160, i: 30
memory: 6160, i: 31
memory: 6160, i: 32
memory: 6160, i: 33
memory: 6160, i: 34
memory: 6160, i: 35
memory: 6160, i: 36
memory: 6160, i: 37
memory: 6160, i: 38
memory: 6160, i: 39
memory: 6160, i: 40
memory: 6160, i: 41
memory: 6160, i: 42
memory: 6160, i: 43
memory: 6160, i: 44
memory: 6160, i: 45
memory: 6160, i: 46
memory: 6160, i: 47
memory: 6160, i: 48
memory: 6160, i: 49
memory: 6160, i: 50
memory: 6160, i: 51
memory: 6160, i: 52
memory: 6160, i: 53
memory: 6160, i: 54
memory: 6160, i: 55
memory: 6160, i: 56
memory: 6160, i: 57
memory: 6160, i: 58
memory: 6160, i: 59
memory: 6160, i: 60
memory: 6160, i: 61
memory: 6160, i: 62
memory: 6160, i: 63
memory: 6160, i: 64
memory: 6160, i: 65
memory: 6160, i: 66
memory: 6160, i: 67
memory: 6160, i: 68
memory: 6160, i: 69
memory: 6160, i: 70
memory: 6160, i: 71
memory: 6160, i: 72
memory: 6160, i: 73
memory: 6160, i: 74
memory: 6160, i: 75
memory: 6160, i: 76
memory: 6160, i: 77
memory: 6160, i: 78
memory: 6160, i: 79
memory: 6160, i: 80
memory: 6160, i: 81
memory: 6160, i: 82
memory: 6160, i: 83
memory: 6160, i: 84
memory: 6160, i: 85
memory: 6160, i: 86
memory: 6160, i: 87
memory: 6160, i: 88
memory: 6160, i: 89
memory: 6160, i: 90
memory: 6160, i: 91
memory: 6160, i: 92
memory: 6160, i: 93
memory: 6160, i: 94
memory: 6160, i: 95
memory: 6160, i: 96
memory: 6160, i: 97
memory: 6160, i: 98
memory: 6160, i: 99
memory: 6160, i: 100
memory: 2680
memory: 2680

Таким образом, оптимальным, без всяких дополнительных затрат, будет вариант с передачей массива по ссылке и использованием for.

Пример
<?php

function doSmth(array &$array, int $memory) {

  printf('memory: %s%s', memory_get_usage() - $memory, PHP_EOL);
  $array[0] = 0;
  printf('memory: %s%s', memory_get_usage() - $memory, PHP_EOL);

  $count = count($array);
  for ($i = 0; $i < $count; $i ++) {
    $array[$i] = 100;
    printf('memory: %s, i: %s%s', memory_get_usage() - $memory, $i, PHP_EOL);
  }

  printf('memory: %s%s', memory_get_usage() - $memory, PHP_EOL);
}

$memory = memory_get_usage();
$array = range(0, 99);
doSmth($array, $memory);
printf('memory: %s%s', memory_get_usage() - $memory, PHP_EOL);
memory: 2648
memory: 2680
memory: 2680, i: 0
memory: 2680, i: 1
memory: 2680, i: 2
memory: 2680, i: 3
memory: 2680, i: 4
memory: 2680, i: 5
memory: 2680, i: 6
memory: 2680, i: 7
memory: 2680, i: 8
memory: 2680, i: 9
memory: 2680, i: 10
memory: 2680, i: 11
memory: 2680, i: 12
memory: 2680, i: 13
memory: 2680, i: 14
memory: 2680, i: 15
memory: 2680, i: 16
memory: 2680, i: 17
memory: 2680, i: 18
memory: 2680, i: 19
memory: 2680, i: 20
memory: 2680, i: 21
memory: 2680, i: 22
memory: 2680, i: 23
memory: 2680, i: 24
memory: 2680, i: 25
memory: 2680, i: 26
memory: 2680, i: 27
memory: 2680, i: 28
memory: 2680, i: 29
memory: 2680, i: 30
memory: 2680, i: 31
memory: 2680, i: 32
memory: 2680, i: 33
memory: 2680, i: 34
memory: 2680, i: 35
memory: 2680, i: 36
memory: 2680, i: 37
memory: 2680, i: 38
memory: 2680, i: 39
memory: 2680, i: 40
memory: 2680, i: 41
memory: 2680, i: 42
memory: 2680, i: 43
memory: 2680, i: 44
memory: 2680, i: 45
memory: 2680, i: 46
memory: 2680, i: 47
memory: 2680, i: 48
memory: 2680, i: 49
memory: 2680, i: 50
memory: 2680, i: 51
memory: 2680, i: 52
memory: 2680, i: 53
memory: 2680, i: 54
memory: 2680, i: 55
memory: 2680, i: 56
memory: 2680, i: 57
memory: 2680, i: 58
memory: 2680, i: 59
memory: 2680, i: 60
memory: 2680, i: 61
memory: 2680, i: 62
memory: 2680, i: 63
memory: 2680, i: 64
memory: 2680, i: 65
memory: 2680, i: 66
memory: 2680, i: 67
memory: 2680, i: 68
memory: 2680, i: 69
memory: 2680, i: 70
memory: 2680, i: 71
memory: 2680, i: 72
memory: 2680, i: 73
memory: 2680, i: 74
memory: 2680, i: 75
memory: 2680, i: 76
memory: 2680, i: 77
memory: 2680, i: 78
memory: 2680, i: 79
memory: 2680, i: 80
memory: 2680, i: 81
memory: 2680, i: 82
memory: 2680, i: 83
memory: 2680, i: 84
memory: 2680, i: 85
memory: 2680, i: 86
memory: 2680, i: 87
memory: 2680, i: 88
memory: 2680, i: 89
memory: 2680, i: 90
memory: 2680, i: 91
memory: 2680, i: 92
memory: 2680, i: 93
memory: 2680, i: 94
memory: 2680, i: 95
memory: 2680, i: 96
memory: 2680, i: 97
memory: 2680, i: 98
memory: 2680, i: 99
memory: 2680
memory: 2680

Ещё раз увеличиваем потребление памяти на ровном месте

Ну и сладкое на десерт. В замечательной статье «Массивы в РНР 7: хэш-таблицы» говорится о том, что массив, точнее его внутреннее представление может храниться в упакованном и классическом виде. В упакованном - значит в сжатом. Сжатым массив создаётся, когда в нем используются только целочисленные ключи и только по порядку, например так:

<?php

$array = [];
$array[] = 'Один';
$array[] = 'Два';
...

Или используя функцию range, как это делалось в коде выше, например:

<?php

$memory = memory_get_usage();
$array = range(0, 99);
printf('memory: %s%s', memory_get_usage() - $memory, PHP_EOL);
$array['qwe'] = 'new item value';
printf('memory: %s%s', memory_get_usage() - $memory, PHP_EOL);

Вывод:

memory: 2616
memory: 8280

Массив начал занимать в 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

$bigArray = range(0, 10000000);
$info = new stdClass;        // $info = []
$info->data = $bigArray;     // $info['data'] = $bigArray;
$info->min = min($bigArray); // $info['min'] = min($bigArray);
$info->max = ...;            // $info['max'] = ...;
...

Справедливости ради отмечу, что утверждение о том, что целочисленные ключи должны идти строго по порядку - не совсем верно. Они могут идти не по порядку до тех пор, пока значение ключа не превысит размер хэш-таблицы, см. раздел «Конструкция хэш-таблицы».

Заключение

Аккуратно работайте с массивами, особенно с большими. Их точно лучше передавать по ссылке, как PHP передаёт объекты. Используйте for. Думайте, проверяйте и замеряйте. Держите массивы упакованными. Рассмотрите возможность использования SplFixedArray.

Тут вообще нужно быть осторожным и проверять всё именно для вашей версии PHP. Работает ли for быстрее foreach на восьмёрке? А на семёрке? А на пятёрке? Т.е. всё то, что написано, верно для моей версии PHP на моём компьютере, но верно ли для вас - вопрос.

P. S.

Теги:
Хабы:
Всего голосов 43: ↑43 и ↓0+43
Комментарии56

Публикации

Истории

Работа

Ближайшие события

27 августа – 7 октября
Премия digital-кейсов «Проксима»
МоскваОнлайн
11 сентября
Митап по BigData от Честного ЗНАКа
Санкт-ПетербургОнлайн
14 сентября
Конференция Practical ML Conf
МоскваОнлайн
19 сентября
CDI Conf 2024
Москва
20 – 22 сентября
BCI Hack Moscow
Москва
24 сентября
Конференция Fin.Bot 2024
МоскваОнлайн
25 сентября
Конференция Yandex Scale 2024
МоскваОнлайн
28 – 29 сентября
Конференция E-CODE
МоскваОнлайн
28 сентября – 5 октября
О! Хакатон
Онлайн
30 сентября – 1 октября
Конференция фронтенд-разработчиков FrontendConf 2024
МоскваОнлайн