Skip to content

Memory exhausted issues #662

Open
Open
@CodiMech25

Description

So, in the last 3-4 hours i was searching for a memory leak in my app. After a complete code-review of my application code i decided to make a new simple app built on Ratchet WS server and see, if the problem persists. And it did!

The problem was, that whenever i created a WS connection, the connection class instances built in the background of the Ratchet were not destroyed! So on every new connection was created a new connection class with event listeners and by dropping this connection on the client side, this background instance still exists. Because of this, my memory usage was something like this:

(i was running a PHP Ratchet WS server and testing from a JS client in the browser)

New connection
Memory usage: 2.00 MB | Max. memory: 3.00 MB
Connection dropped by client
New connection
Memory usage: 2.05 MB | Max. memory: 3.00 MB
Connection dropped by client
New connection
Memory usage: 2.10 MB | Max. memory: 3.00 MB
Connection dropped by client
New connection
Memory usage: 2.15 MB | Max. memory: 3.00 MB
Connection dropped by client
...
and so on, you get thw idea.

Then, of course, the PHP script throwed a "Max memory limit exceeded" error.

The fix for this is quite simple:

OLD
Ratchet/src/Ratchet/Server/IoServer.php

    public function handleEnd($conn) {
        try {
            $this->app->onClose($conn->decor);
        } catch (\Exception $e) {
            $this->handleError($e, $conn);
        }
        unset($conn->decor);
    }

NEW
Ratchet/src/Ratchet/Server/IoServer.php

    public function handleEnd($conn) {
        try {
            $this->app->onClose($conn->decor);
        } catch (\Exception $e) {
            $this->handleError($e, $conn);
        }

        unset($conn->decor);

        $conn->removeAllListeners();
        gc_collect_cycles();
    }

I think, you can even skip the $conn->removeAllListeners(); line, because the $conn class has no more instances at this time anyway.

So, now it seems to work pretty nice, no memory leak whatsoever.

But there is one thing i don't get, why isn't the garbage collector collecting things automatically when the memory limit is so near?

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions