Capturing (externally) the memory consumption of a given Callback

前端 未结 3 473
小蘑菇
小蘑菇 2020-12-21 15:04

The Problem

Lets say I have this function:

function hog($i = 1) // uses $i * 0.5 MiB, returns $i * 0.25 MiB
{
    $s = str_repeat(\'a\', $i * 1024 *          


        
3条回答
  •  无人及你
    2020-12-21 15:37

    I found this: github.com/kampaw/profiler that seem to use the "tick/register/decare-concept", that wasn't an option for you. I've also read that the register_tick_functionality is going to removed in PHP 6. (But that might just be a rumour)

    I understand totally what you mean by checking memory INSIDE of the function.

    I've tested your code based on just calling the function and then returning memory usage afterward using that function. I made a checkMemoryFunction() just make it more general (of course checkMemoryFunction would take a bit of memory to, but that might be possible to subtract if necessary). I think you were thinking right about getting used memory, BUT I found another very weird thing...

    ...with this code:

     $value)
    {
        $mem = checkMemoryFunction('hog', $key);
        $iterations[$key] = $mem;
    }
    
    $peak = max($iterations);
    echo '
    Iteratins array:'; print_r($iterations); echo 'memory peak=' . $peak; ?>

    I got about same results as you did: (First element set, but not the rest)

    Output Iterations array:

    Array ( [0] => 312 [10] => 0 [20] => 0 [30] => 0 [40] => 0 [50] => 0 [45] => 0 [35] => 0 [25] => 0 [15] => 0 [5] => 0 ) memory peak=312
    

    However, when I add rows to set each key-value to 0 (or whatever value)...

    $iterations = array_merge(range(0, 50, 10), range(50, 0, 5));
    $iterations = array_fill_keys($iterations, 0);
    
    // set each value to 0 in array
    foreach ($iterations as $key => &$value)
    {
        $value = 0;
    }
    
    foreach ($iterations as $key => $value)
    {
        $mem = checkMemoryFunction('hog', $key);
        $iterations[$key] = $mem;
    }
    

    ...I get these values (some memory usage for all function calls):

    Array ( [0] => 312 [10] => 24 [20] => 24 [30] => 24 [40] => 24 [50] => 24 [45] => 24 [35] => 24 [25] => 24 [15] => 24 [5] => 24 ) memory peak=312
    

    So it seems like the problem lied within the call to array_fill_keys(). (It seems like the array-elements aren't initilized in some weird way)

    Taking a close look at $iterations-array directly in your code after merging the arrays, it look like this: (duplicate values)

    Array ( [0] => 0 [1] => 10 [2] => 20 [3] => 30 [4] => 40 [5] => 50 [6] => 50 [7] => 45 [8] => 40 [9] => 35 [10] => 30 [11] => 25 [12] => 20 [13] => 15 [14] => 10 [15] => 5 [16] => 0` )
    

    but I think what you really wanted was something like this:

    Array ( [0] => 0 [1] => 10 [2] => 20 [3] => 30 [4] => 40 [5] => 50 [6] => 45 [8] => 35 [10] => 25 [12] => 15 [14] => 5) 
    

    My suspicion was that the duplicates made array_fill_keys() act in strange manner, so I tried:

    $iterations = array(0, 10, 20, 30, 40, 50, 45, 35, 25, 15);
    $iterations = array_fill_keys($iterations, 0);
    foreach ($iterations as $key => $value)
    {
            $mem = checkMemoryFunction('hog', $key);
            $iterations[$key] = $mem;
    }
    

    But it still didn't work as expected:

    Array ( [0] => 312 [10] => 0 [20] => 0 [30] => 0 [40] => 0 [50] => 0 [45] => 0 [35] => 0 [25] => 0 [15] => 0 ) memory peak=312
    

    When I add

    foreach ($iterations as $key => &$value)
    {
        $value = 0;
    }
    

    again it workds like expected:

    Array ( [0] => 312 [10] => 0 [20] => 24 [30] => 24 [40] => 24 [50] => 24 [45] => 32 [35] => 48 [25] => 24 [15] => 24 [5] => 24 ) memory peak=312
    

    I think it's strange because array_fill_keys($iterations, 0); should do the same thing as the foreach above. I can't figure out WHY it doesn't work as expected. Maybe it's a bug, but probably it's something "stupid" that I haven't thought of.

    Another approach could be like storing "content inside a function" from theh PHP-source-file and then save it as profile/hog.php and after that execute the hog.php code.

    I hope this could help you out a bit! :-)

提交回复
热议问题