Higher CPU usage compare to swoole itself
foremtehan opened this issue · comments
I wanted to test the framework. So far, it's good, but i've noticed that it consumes more cpu compared to Swoole itself.
these are the changes i made to the framework:
composer require hyperf/database-pgsql
edited the database config:
return [
'default' => [
'driver' => 'pgsql',
'host' => '',
'database' => '',
'port' => 5432,
'username' => '',
'password' => "",
'charset' => env('DB_CHARSET', 'utf8'),
'collation' => env('DB_COLLATION', 'utf8_unicode_ci'),
'prefix' => '',
'schema' => 'public',
'pool' => [
'min_connections' => 1,
'max_connections' => 10,
'connect_timeout' => 10.0,
'wait_timeout' => 3.0,
'heartbeat' => -1,
'max_idle_time' => (float) env('DB_MAX_IDLE_TIME', 60),
],
'commands' => [
'gen:model' => [
'path' => 'app/Model',
'force_casts' => false,
'inheritance' => 'Model',
'refresh_fillable' => true
],
],
]
];
Default Controller:
class IndexController extends AbstractController
{
public function index()
{
return Db::table('users')->first();
}
}
ab -c 300 -n 20000 http://ip:port
Now same thing in the swoole:
<?php
require __DIR__.'/vendor/autoload.php';
use Illuminate\Database\Capsule\Manager as Capsule;
use Swoole\Http\Request;
use Swoole\Http\Response;
use Swoole\Http\Server;
$capsule = new Capsule;
$capsule->addConnection([
'driver' => 'pgsql',
'host' => 'postgres',
'database' => 'your_db_name',
'username' => 'your_db_user',
'password' => 'your_db_password',
'charset' => 'utf8',
'collation' => 'utf8_unicode_ci',
'prefix' => '',
]);
// Set the event dispatcher used by Eloquent models... (optional)
use Illuminate\Events\Dispatcher;
use Illuminate\Container\Container;
// Make this Capsule instance available globally via static methods... (optional)
$capsule->setAsGlobal();
// Setup the Eloquent ORM... (optional; unless you've used setEventDispatcher())
$capsule->bootEloquent();
$http = new Server('0.0.0.0', 9501);
$http->on(
'start',
function (Server $http) {
echo "Swoole HTTP server is started.\n";
}
);
$http->on(
'request',
function (Request $request, Response $response) use($capsule, $bot) {
$result = $capsule->connection()->table('users')->first();
$response->end($result);
}
);
$http->start();
This test was conducted on a server with 4gb ram and a 2 cpu (2.5GHz) setup. Do I need to modify anything to reduce cpu usage, or is this just how it is?
In the Illuminate library setup you provided, the Capsule Manager does indeed add a database connection, but it doesn't explicitly define a connection pool. Each time a request is made to the database, a new connection may be established, without much control over connection reuse or management. This can lead to potential inefficiencies, especially in high-concurrency scenarios, as opening and closing connections frequently can incur unnecessary overhead.
On the other hand, the Hyperf framework configuration explicitly defines a connection pool for PostgreSQL. By specifying parameters like min_connections, max_connections, and other pool-related settings, Hyperf effectively manages a pool of database connections. This approach is more efficient, as it maintains a set of pre-established connections that can be reused as needed, reducing the overhead of connection establishment and teardown (but can higher CPU usage).
Start Hyperf application and execute:
ab -c 300 -n 20000 http://ip:port
Later, execute in PostgreSQL:
SELECT
usename AS username,
COUNT(*) AS total_connections
FROM
pg_stat_activity
GROUP BY
usename;
...Make equal process in swoole application and verify :)
In your config file server.app
is defined like:
return [
'mode' => SWOOLE_PROCESS,
'servers' => [
[
'name' => 'http',
'type' => Server::SERVER_HTTP,
'host' => '0.0.0.0',
'port' => 9501,
'sock_type' => SWOOLE_SOCK_TCP,
'callbacks' => [
Event::ON_REQUEST => [Hyperf\HttpServer\Server::class, 'onRequest'],
],
],
],
'settings' => [
Constant::OPTION_ENABLE_COROUTINE => true,
Constant::OPTION_WORKER_NUM => swoole_cpu_num(), // <- CHANGE TO 1 CPU WORKER AND VERIFY
Constant::OPTION_PID_FILE => BASE_PATH . '/runtime/hyperf.pid',
Constant::OPTION_OPEN_TCP_NODELAY => true,
Constant::OPTION_MAX_COROUTINE => 100000,
Constant::OPTION_OPEN_HTTP2_PROTOCOL => true,
Constant::OPTION_MAX_REQUEST => 100000,
Constant::OPTION_SOCKET_BUFFER_SIZE => 2 * 1024 * 1024,
Constant::OPTION_BUFFER_OUTPUT_SIZE => 2 * 1024 * 1024,
],
'callbacks' => [
Event::ON_WORKER_START => [Hyperf\Framework\Bootstrap\WorkerStartCallback::class, 'onWorkerStart'],
Event::ON_PIPE_MESSAGE => [Hyperf\Framework\Bootstrap\PipeMessageCallback::class, 'onPipeMessage'],
Event::ON_WORKER_EXIT => [Hyperf\Framework\Bootstrap\WorkerExitCallback::class, 'onWorkerExit'],
],
];
Function swoole_cpu_num()
in your case added 2 cpu workers and consume higher CPU.
Hyperf start full complete server with various components. Normal consume CPU Hyperf be higher what Swoole simple app.
'mode' => SWOOLE_BASE
really...