Разница между неустановленным и = нулевым
Если вы делаете $what = null; тогда вы переписываете данные переменной. Вы можете освободить / сжать память быстрее, но это может украсть циклы ЦП из кода, который действительно в них нуждается, быстрее, что приведет к увеличению общего времени выполнения.
Видимо, это неоспоримая истина, поэтому, возможно, кто-то будет так любезен, чтобы объяснить.
Я имею в виду, что, делает unset
волшебно не выполнять никаких инструкций по сборке, тогда как $whatever = null;
делает? Ответ, как дано, примерно так же полезен, как сказать
$what = null сбрасывает буфер и кэш L1, тогда как unset очищает буфер и сбрасывает кэш L2.
Techno Mumbo Jumbo не является ответом.
6 ответов
Важное различие между обоими методами заключается в том, что unset($a)
также удаляет $a
из таблицы символов; например:
$a = str_repeat('hello world ', 100);
unset($a);
var_dump($a);
Выходы:
Notice: Undefined variable: a in xxx
NULL
Но когда $a = null
используется:
$a = str_repeat('hello world ', 100);
$a = null;
var_dump($a);
Выходы:
NULL
Я прогнал код через тест, а также обнаружил, что $a = null
примерно на 6% быстрее, чем его unset()
коллега. Кажется, что обновление записи таблицы символов происходит быстрее, чем ее удаление.
добавление
Другое отличие (как видно из этого небольшого скрипта) заключается в том, сколько памяти восстанавливается после каждого вызова:
echo memory_get_usage(), PHP_EOL;
$a = str_repeat('hello world ', 100);
echo memory_get_usage(), PHP_EOL;
// EITHER unset($a); OR $a = null;
echo memory_get_usage(), PHP_EOL;
Когда используешь unset()
все, кроме 64 байтов памяти возвращаются, тогда как $a = null;
освобождает все, кроме 272 байтов памяти. У меня недостаточно знаний, чтобы понять, почему между обоими методами существует разница в 208 байт, но, тем не менее, это разница.
При использовании unset использование памяти и время обработки меньше.
Приведенные выше ответы великолепны, особенно комментарий: "Важное различие между обоими методами заключается в том, что unset($a) также удаляет $ a из таблицы символов".
Однако я не думаю, что кто-то действительно полностью ответил на вопрос, потому что они не описывают, как они используются. Хорошо, я думаю, мы знаем, что они в основном делают одно и то же. Зачем использовать один над другим?
ноль
быстрее восстанавливает память, несмотря на то, что PHP самостоятельно управляет памятью / сборкой мусора.
снята с охраны ()
также восстанавливает память, но это скорее "когда я могу добраться до нее" и поэтому считается более быстрым, так как не выделяет ей ресурсы сразу.
Когда следует использовать null против unset?
Это зависит от вашей скорости и потребностей в данных, например, чтение большого массива из memcache/ или DB только для того, чтобы взять часть данных и поместить их в другой, гораздо меньший массив подмножеств, может быть хорошим кандидатом на нулевое значение, потому что в противном случае вы можете в конечном итоге хранение всех этих других данных до завершения функции, которая может накапливаться и вызывать 500 ошибок для вашего веб-приложения. Примечание: в этом сценарии вы захотите сделать одно или другое, несмотря ни на что. Unset следует отдавать предпочтение, когда важна скорость (если не так, я полагаю), и при этом мало внимания уделяется наращиванию памяти.
Пример: Взятие большого массива и помещение его в MemCache:
list($inv1, $inv2, $inv3, $inv4) = array_chunk($inventory_array),
ceil(count($val['inventory']) / 4));
MemCache::set($cacheKeyInv1, $inv1, $expiry);
MemCache::set($cacheKeyInv2, $inv2, $expiry);
MemCache::set($cacheKeyInv3, $inv3, $expiry);
MemCache::set($cacheKeyInv4, $inv4, $expiry);
for ($i = 1; $i < 5; $i++) {
${"inv" . $i} = null;
}
Цикл for очищает данные, можно использовать null или unset, но, поскольку это большой набор данных, возможно, null предпочтительнее, поскольку он быстрее восстанавливает память.
Я сделал простой тест.
Рассматривая простой класс, подобный этому:
class Cat{
public $eyes = 2;
public $claws = 4;
public $name = "Kitty";
public $sound = ['Meow', 'Miaou'];
}
Я запускаю этот код
$start = microtime(true);
for($i = 10000000; $i > 0; --$i){
$cat = new Cat;
$cat = null;
}
$end = microtime(true);
printf("Run in %s and use %s memory",
round($end - $start, 2), round(memory_get_usage() / 1000, 2));
Запустите в 1.95 и используйте 233.29 памяти
И это
for($i = 10000000; $i > 0; --$i){
$cat = new Cat;
unset($cat);
}
Запустите в 2.28 и используйте 233,1 памяти
Ибо то, что стоит, кажется, null
метод работает быстрее.
Используя код
$a = str_repeat('hello world ', 10000);
$start1 = microtime(true);
unset($a);
$stop1 = microtime(true);
$a = str_repeat('hello world ', 10000);
$start2 = microtime(true);
$a = null;
$stop2 = microtime(true);
echo 'unset time lap of '. ( $stop1 - $start1 ) .'<br>';
echo 'null time lap of '. ( $stop2 - $start2 ) .'<br>';
в 10 раз:
unset time lap of 5.0067901611328E-6
null time lap of 1.1920928955078E-6
unset time lap of 9.5367431640625E-7
null time lap of 9.5367431640625E-7
unset time lap of 0
null time lap of 9.5367431640625E-7
unset time lap of 2.1457672119141E-6
null time lap of 1.1920928955078E-6
unset time lap of 2.1457672119141E-6
null time lap of 0
unset time lap of 9.5367431640625E-7
null time lap of 0
unset time lap of 1.9073486328125E-6
null time lap of 9.5367431640625E-7
unset time lap of 9.5367431640625E-7
null time lap of 0
unset time lap of 1.9073486328125E-6
null time lap of 9.5367431640625E-7
unset time lap of 0
null time lap of 0
Похоже, что нулевое присваивание чаще занимает меньше времени.
Разница в том, что присваивание нулевого значения является присвоением нулевого значения, а не деинициализацией. Если вы не работаете над критической проблемой производительности, вы отключите использование unset, если вы проверяете обе возможности на своей версии PHP. Основное отличие произошло с PHP 7.4 и типами свойств, вы можете отменить свойство, не допускающее значение null, но вы не можете назначить значение null.
class C {
public int $value;
}
$c = new C();
var_dump(isset($c->value)); // false
$c->value = 5;
var_dump($c->value); //5
unset($c->value);
//var_dump($c->value); //Error: Typed property C::$value must not be accessed before initialization
var_dump(isset($c->value)); // false
$c->value = 5;
$c->value = null; //Error Typed property C::$value must be int, null used