Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[bug] stream_select memory leak #209

Open
ging-dev opened this issue Jul 23, 2023 · 7 comments
Open

[bug] stream_select memory leak #209

ging-dev opened this issue Jul 23, 2023 · 7 comments
Labels
bug Something isn't working

Comments

@ging-dev
Copy link

Describe the bug / 问题描述
Test with react/http package

<?php

use React\EventLoop\Loop;
use React\Http\Message\Response;
use React\Promise\Deferred;

require 'vendor/autoload.php';

ini_set('memory_limit', '-1');

$http = new React\Http\HttpServer(function (Psr\Http\Message\ServerRequestInterface $request) {
    $deferred = new Deferred();
    $deferred->resolve('Hello, World');

    return $deferred->promise()->then(function ($data) {
        return new Response(200, body: $data);
    });
});

$socket = new React\Socket\SocketServer('127.0.0.1:8080');
$http->listen($socket);

Loop::run();

Test with wrk -t4 -c400 -d10s http://127.0.0.1:8080 memory keeps increasing in 3 runs this command. The file descriptors don't seem to be closed.

Expected behavior / 正确的行为
No leaks

Outputs / 程序输出

Runtime Environment / 运行环境

Swow

Status => enabled
Author => Swow Team
Link => https://github.com/swow/swow
Contact => Twosee <twosee@php.net>
Version => 1.3.2-dev ( ZTS )
Built => Jun 29 2023 05:11:32
Context => boost-context
Scheduler => libuv-event
SSL => OpenSSL 3.1.1 30 May 2023
cURL => libcurl/8.1.2 OpenSSL/3.1.1 zlib/1.2.13 brotli/1.0.9 zstd/1.5.5 libssh2/1.11.0 nghttp2/1.54.0
@ging-dev ging-dev added the bug Something isn't working label Jul 23, 2023
@twose
Copy link
Member

twose commented Aug 5, 2023

I have not observed any memory leaks or file descriptor leaks.

The memory pool mechanism in PHP only supports one-way expansion. It does not support contraction, so the memory usage will stay at its peak and eventually stabilize at a specific value. Afterward, memory usage is no longer directly related to the number of requests made.

Furthermore, based on my local testing results, the memory usage and file descriptor count show consistent results whether the Swow extension is enabled or disabled.

Can you provide your test data for further investigation of the issue?

@ging-dev
Copy link
Author

ging-dev commented Aug 5, 2023

I have not observed any memory leaks or file descriptor leaks.

The memory pool mechanism in PHP only supports one-way expansion. It does not support contraction, so the memory usage will stay at its peak and eventually stabilize at a specific value. Afterward, memory usage is no longer directly related to the number of requests made.

Furthermore, based on my local testing results, the memory usage and file descriptor count show consistent results whether the Swow extension is enabled or disabled.

Can you provide your test data for further investigation of the issue?

I using swow from https://github.com/hyperf/box
After several times executing the wrk command as described above, I get the error:

Warning: stream_select(): You MUST recompile PHP with a larger value of FD_SETSIZE.
It is set to 1024, but you have descriptors numbered at least as high as 1211.

and my RAM keeps increasing.

This won't happen on native php, Is the problem in https://github.com/hyperf/box? do you have any ideas?

@twose
Copy link
Member

twose commented Aug 7, 2023

You can use the following method to check the number of file descriptors for the corresponding process to determine if there is indeed a leak. If the issue does exist, I am more inclined to believe it is a compatibility issue with the React code (or differences in operating systems), as Swow is not specifically designed for frameworks like React. Hyperf Box is more suitable for building Hyperf projects, and for high-performance, I would recommend using Hyperf. Using both Box and React, you won't be able to gain any benefits from Box.

在Linux上:
ls /proc/PID/fd | wc -l


在macOS上:
lsof -p PID | wc -l


在FreeBSD上:
procstat -v PID | grep "open files" | awk '{print $4}'


在OpenBSD上:
pfiles PID 2>/dev/null | wc -l

@ging-dev
Copy link
Author

ging-dev commented Aug 7, 2023

You can use the following method to check the number of file descriptors for the corresponding process to determine if there is indeed a leak. If the issue does exist, I am more inclined to believe it is a compatibility issue with the React code (or differences in operating systems), as Swow is not specifically designed for frameworks like React. Hyperf Box is more suitable for building Hyperf projects, and for high-performance, I would recommend using Hyperf. Using both Box and React, you won't be able to gain any benefits from Box.

在Linux上:
ls /proc/PID/fd | wc -l


在macOS上:
lsof -p PID | wc -l


在FreeBSD上:
procstat -v PID | grep "open files" | awk '{print $4}'


在OpenBSD上:
pfiles PID 2>/dev/null | wc -l

with the swow extension enabled, after the wrk -t4 -c400 -d10s http://127.0.0.1:8080 command completes, the fd count falls around ~400 and they don't seem to be closed, the fd count doesn't decrease to the original amount like native behavior.

@twose
Copy link
Member

twose commented Aug 7, 2023

Could you use uname -a, php -v and php -m to show me your environment?

@ging-dev
Copy link
Author

ging-dev commented Aug 7, 2023

Could you use uname -a, php -v and php -m to show me your environment?

Linux Latitude-3510 5.15.0-78-generic #85-Ubuntu SMP Fri Jul 7 15:25:09 UTC 2023 x86_64 x86_64 x86_64 GNU/Linux
PHP 8.2.7 (cli) (built: Jun 29 2023 05:13:17) (ZTS)
Copyright (c) The PHP Group
Zend Engine v4.2.7, Copyright (c) Zend Technologies
    with Zend OPcache v8.2.7, Copyright (c), by Zend Technologies
[PHP Modules]
bcmath
bz2
Core
ctype
curl
date
dom
fileinfo
filter
hash
iconv
json
libxml
mbstring
mysqli
mysqlnd
openssl
pcntl
pcre
PDO
pdo_mysql
Phar
posix
random
redis
Reflection
session
SimpleXML
sockets
SPL
standard
Swow
sysvmsg
sysvsem
sysvshm
tokenizer
xml
xmlreader
xmlwriter
yaml
Zend OPcache
zip
zlib
zstd

[Zend Modules]
Zend OPcache

@ciricode
Copy link

a simpler test case to reproduce this bug:

<?php

$socket = stream_socket_server("tcp://localhost:8000", $errno, $errstr);

if (!$socket) {
    die("Error: $errno - $errstr");
}

$clients = array($socket);

while (true) {
    $read = $clients;
    $write = $except = null;

    if (stream_select($read, $write, $except, null) === false) {
        break;
    }

    if (in_array($socket, $read)) {
        $newClient = stream_socket_accept($socket);

        if ($newClient) {
            $clients[] = $newClient;
            echo "New client connected\n";
        }

        unset($read[array_search($socket, $read)]);
    }

    foreach ($read as $client) {
        $data = fread($client, 1024);

        if ($data === false) {
            $key = array_search($client, $clients);
            fclose($client);
            unset($clients[$key]);
        } elseif ($data === '') {
            $key = array_search($client, $clients);
            fclose($client);
            unset($clients[$key]);
            echo "Client disconnected\n";
        } else {
            $response = "HTTP/1.1 200 OK\r\n";
            $response .= "Content-Type: text/plain\r\n";
            $response .= "Content-Length: 12\r\n\r\n";
            $response .= "Hello, world";

            fwrite($client, $response);
        }
    }
}

fclose($socket);

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

3 participants