Не пойму, как php выделяет память

Farsh

~ on ~ high ~ wave ~
Представим теоретическую задачу:
Есть список текстов, нужно для каждого текста составить массив [слово => кол-во вхождений в этот текст]

Генерировать тексты будем сами; например так:
PHP:
        $texts = array();
        for($i=0; $i<1000; ++$i)
        {
            $words = array();
            for($z=0; $z<1000; ++$z)
            {
                $words[] = md5(mt_rand(1, 10000));
            }
            
            $texts[$i] = implode(' ', $words);
        }
Тут мы генерируем 1 тысячу текстов, в каждом 1 тысяча слов. Кол-во уникальных слов на весь корпус = 10 тысяч.

Пример №1, без ссылок:
PHP:
        $textKeyToWordToCnt = array();
        foreach($texts as $textKey => $text)
        {
            $textKeyToWordToCnt[$textKey] = array();
            $words = explode(' ', $text);
            
            foreach($words as $word)
            {
                if(!array_key_exists($word, $textKeyToWordToCnt[$textKey]))
                {
                    $textKeyToWordToCnt[$textKey][$word] = 0;
                }
                
                ++$textKeyToWordToCnt[$textKey][$word];
            }
        }
Xdebug показывает используемую память:
перед началом генерации текстов: 28553844
перед началом обработки текстов: 61861172
после обработки текстов: 165037160

Пример №2, c ссылками:
PHP:
        $h = array();
        $textKeyToWordAndCnt = array();
        
        foreach($texts as $textKey => $text)
        {
            $textKeyToWordAndCnt[$textKey] = array();
            $words = explode(' ', $text);
            
            $wordToCnt = array();
            foreach($words as $word)
            {
                if(!array_key_exists($word, $wordToCnt))
                {
                    $wordToCnt[$word] = 0;
                }
                
                ++$wordToCnt[$word];
            }
            
            foreach($wordToCnt as $word => $cnt)
            {
                if(!array_key_exists($word, $h))
                {
                    $h[$word] = $word;
                }
                
                $textKeyToWordAndCnt[$textKey][] = array(
                    &$h[$word], $cnt
                );
            }
        }
Все просто - храним один массив со всеми уникальным словами, коих будет 10000, а при обработке текстов ссылаемся на него, что, в теории, должно сэкономить память.

Но результаты оказались иными:
перед началом генерации текстов: 28557252
перед началом обработки текстов: 61863696
после обработки текстов: 331917160

То есть стало использоваться в 2 раза больше памяти

Вопрос:
почему такое происходит ?
 

tony2001

TeaM PHPClub
попробуй как-то попроще объяснить что именно тебе надо.
я запутался в этих кэмелКейсах пытаясьПонять чтоТыХочешьСделать.
 

Farsh

~ on ~ high ~ wave ~
tony2001
Окей, другой пример:

PHP:
        $h = array();
        for($i=0; $i<100; ++$i)
        {
            $md5 = md5($i);
            $h[$md5] = $md5;
        }
        
        $h2 = array();
        for($i=0; $i<1000000; ++$i)
        {
            $randomMd5 = md5(mt_rand(0, 99));
            $h2[$i] =& $h[$randomMd5];
        }
От этого куска кода я ожидал, что в памяти будет пул из 100 строковых объектов и 1 миллион ссылок.
Реально же выделяется 1 миллион строк.

И вопрос был таков: почему так происходит ?
 

Ирокез

бессмертный пони
Команда форума
Партнер клуба
Farsh
интересно, задал бы ты подобный вопрос, если бы осмыслил что написал. особенно
PHP:
$h2[$i] =& $h[$randomMd5];
т.е. если откинуть весь г.код, по твоему что такое массив. и каким чудесным образом, мульен элементов, должно превратиться в 100
 

tz-lom

Продвинутый новичок
http://www.php.net/manual/en/language.references.arent.php

а вообще тест неправильный тем что размер данных слишком мал, структуры в PHP занимают гораздо больше
замени $h[$md5] = $md5; на
$h[$md5] = str_repeat($md5,10000);
и ты увидишь что использование памяти в втором случае не увеличилось, это не копия
а теперь главное - убери референс и....
нет,за память ты не вылезешь, есть такая штука - copy on write , вот она и задействованна, и пока оригинальные данные не изменятся эта структура будет занимать меньше чем должна
 

Farsh

~ on ~ high ~ wave ~
Ирокез
т.е. если откинуть весь г.код, по твоему что такое массив. и каким чудесным образом, мульен элементов, должно превратиться в 100
Я же привел конкретный пример из 10 строк кода и того, чего я ожидал: 100 строковых объектов и 1 миллион ссылок на них.
Где ты там 100 элементов увидел - ума не приложу.
Если тебе слабо в этом разобраться - мне тебя жаль

структуры в PHP занимают гораздо больше
Да, это я уже понял

и ты увидишь что использование памяти в втором случае не увеличилось, это не копия
и действительно - спасибо!

есть такая штука - copy on write
про это знал, но еще раз спасибо!
 
Сверху