chobie / php-uv

libuv php extension
184 stars 21 forks source link

Timer mem leaks #45

Closed igorw closed 11 years ago

igorw commented 11 years ago

Not sure if other parts are affected as well, but the timers are definitely leaking. Possibly refcounts are not being decreased properly, because the callback is not being garbage collected.

See this PR for react and the examples/test-memory.php script.

chobie commented 11 years ago

@igorw that PR is little bit long. do you mean execute test-memory.php with React\EventLoop\LibUvLoop seems leaking?

https://github.com/csaoh/react/blob/libuv-filesystem/examples/test-memory.php

I saw above file. uv_timer is able to stop and start when you want. so calling uv_timer_stop does not decrease refcount.

$loop->addPeriodicTimer(0.001, function () use (&$i, $loop) {
    $i++;

    $loop->addPeriodicTimer(1, function ($timer) {
        $timer->cancel();
    });
});

https://github.com/csaoh/react/blob/libuv-filesystem/src/React/EventLoop/LibUvLoop.php#L129

I think this internal addPeriodicTimer block stacks lambda function into memory each time. probably uv_stop and unset($this->timers[$timer]) will free the memory.

I didn't check carefully so I missed something. hope this help you

igorw commented 11 years ago

But I don't want to uv_stop. In a long running process it is very important to clear the timer without exiting the loop.

And the unset was indeed an issue, that has been fixed in the current LibUvLoop, see ->detach($timer).

chobie commented 11 years ago

maybe uv_unref($timer) will fix the problem. please try uv_unref and detach.

<?php

$timer = uv_timer_init();
uv_timer_start($timer, 1, 1, function($timer, $stat) {
    $internal_timer = uv_timer_init();
    uv_timer_start($internal_timer,1,1, function ($timer, $stat) use($storage){
        uv_timer_stop($timer);
        uv_unref($timer);
    });
});

$reporter = uv_timer_init();
uv_timer_start($reporter, 1000, 1000, function($timer, $stat) use (&$i) {
    $kmem = memory_get_usage(true) / 1024;
    echo "Run: $i\n";
    echo "Memory: $kmem KiB\n";
});

uv_run();

explain this behavior is difficult for me. it's not leaking just retaining.

IMG_0633

callback and timer refcounting is a big monster.

igorw commented 11 years ago

That indeed solves the problem. Thanks!