amphp / mysql

An async MySQL client for PHP, optimizing database interactions with efficient non-blocking capabilities. Perfect for responsive, high-performance applications.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Connection open + one select + close takes about 30 ms

mvorisek opened this issue · comments

I am debugging a php-src 9151 issue and I decided to use this library to check if the issue is present with pure PHP MySQL impl. too or not.

My code looks like:

foreach (range(0, 10_000) as $i) {
    $pdo = null;
    try {
        $res = null;
        \Amp\Loop::run(function () use ($dbHost, $dbUser, $dbPassword, $dbDatabase, &$res) {
            $db = \Amp\Mysql\pool(\Amp\Mysql\ConnectionConfig::fromString(
                'host=' . $dbHost . ';user=' . $dbUser . ';pass=' . $dbPassword . ';db=' . $dbDatabase
            ));

            /** @var \Amp\Mysql\ResultSet $result */
            $result = yield $db->query('SELECT \'test\' as v');

            $res = [];
            while (yield $result->advance()) {
                $res[] = $result->getCurrent();
            }

            $db->close();
        });
        $this->assertSame([['v' => 'test']], $res);
    } catch (\Exception $e) {
        throw new \Exception('Failed after ' . $i . ' iterations', 0, $e);
    }
}

But it executes more than 10x slower than similar open connection + one select query + close connection code with native \PDO driver.

With amp/mysql the time per iteration is about 30 ms. But I would expect no more than 5 ms / iter. in average.

My question is, why is amp/mysql so slow and can I improve the code above somehow?

Please note, it is intentional to close and reopen the connection in each iteration for my test usecase.

Please try opening a single connection instead of creating a new pool and closing it each time. I expect it to be a bit slower, but we should investigate what makes it that much slower.

FYI, without a pool ($db = yield \Amp\Mysql\connect(\Amp\Mysql\ConnectionConfig::fromString(...));) it is a little faster, but still very slow. I run is several times and I cannot get under 20s / 1000 iters.

I think this is probably mainly caused by PDO using the old mysql_native_password, while amphp/mysql supports the newer caching_sha2_password pluggable authentication. caching_sha2_password however, comes with quite some cost, because the client needs to fetch the server's public key and computed openssl_public_encrypt (which takes about 13% in my benchmark).

@mvorisek Turns out there was a bug in the caching_sha2_password implementation, which made it always to a full authentication roundtrip instead of using the fast auth flow.

I'm at 3s for 1000 iterations now instead of 7s with a local mysql docker container.

@kelunik nice finding, thank you ❤️