Estou criando um grande array PHP e então removo a maior parte do começo dele. Como sabemos, isso não libera a memória, apenas marca os itens removidos como Undef, conforme explicado por Nikita aqui . No entanto, quando coloco mais itens no array, ele deve atingir o ponto de compactação e devemos ver a redução de memória, mas isso não é observado.
Por favor, ajude-me a entender por que a compactação não está acontecendo?
<?php
$items = [];
// hashtable compaction should start at every 2^n size.
$size = pow(2, 18);
for($i=0;$i<$size;$i++) {
$items[$i] = "string $i";
}
// at this point we reached the maximum tablesize before compaction
// 2^18 is used to make memory consumpotion visible enough.
printf("mem: %d Mb \n", memory_get_usage(true) / 1024 / 1024);
// Remove all except the last one
for($i=0;$i<$size-1;$i++) {
unset($items[$i]);
}
// here it is expected to see the same memory footprint as nothing is freed,
// only marked as UNDEF.
printf("mem: %d Mb \n", memory_get_usage(true) / 1024 / 1024);
// However here we expect to hit the compaction point
// and see $size-1 elements removed, while 1 added, so memory is expected to go down
$items[] = $i;
printf("mem: %d Mb \n", memory_get_usage(true) / 1024 / 1024);
Exemplo ao vivo: https://onlinephp.io/c/98970
Porque Nikic disse no artigo :
Isso indica que a chamada compactação apenas reorganizará os dados sem reduzir o uso de memória.
Para tabelas hash compactadas, o autor também disse:
Acredito que o PHP usa diretamente
arData
um array regular, então as tabelas de hash compactadas não serão compactadas.No código-fonte atual , pode-se ver que uma tabela hash compactada foi declarada como
zval *arPacked;
, mas ela ainda assim nunca encolhe.No entanto, como o tamanho de
Bucket
é maior quezval
, há uma exceção, quando uma hashtable regular é convertida em uma hashtable compactada, o uso de memória será reduzido (cerca de metade). Algumas funções comosort
podem conseguir isso (surpreendentemente,shuffle
também podem).