swoole / swoole-src

🚀 Coroutine-based concurrency library for PHP
https://www.swoole.com
Apache License 2.0
18.4k stars 3.16k forks source link

Checking out how to speed up MongoDB requests #4527

Open Draghmar opened 2 years ago

Draghmar commented 2 years ago

I'm checking out how could I approach the fact that MongoDB won't work properly with concurrency. My goal is to set this up on Tick that started within WorkerStart event. The reason I wanted to do that is to check if I could query MongoDB in parallel to get all the data faster. This is mostly testing, toying some may say. ;) What I've done first was this:

$wg = new Swoole\Coroutine\WaitGroup();
$out = [];
$chunks = array_chunk($baseBind,3);
foreach($chunks as $bind) {
    go(function() use ($wg,&$out,$bind) {
        $wg->add();
        $mongo = new MongoDB\Driver\Manager(MONGOCONN);
        $query = new MongoDB\Driver\Query($bind);
        $res = $mongo->executeQuery(MONGOCOLL, $query)->toArray();
        foreach($res as $data) $out[] = $data;
        $wg->done();
    });
}
$wg->wait();

where $chunks are the result of array_chunk executed on original $bind where I have the list of entries I want do get. But this approach didn't give me any benefit. The time was exactly the same. Not sure why. "On paper" it looks like it should do the trick. Do you have any suggestions? I don't want to use any frameworks and such. I remember seeing some github repository that was using some...approach from MongoDB by using sockets(?) but I can't find it any more.

leocavalcante commented 2 years ago

The MongoDB driver for PHP is a layer for the original driver in C, so unfortunately Swoole can't hook on that like it does for php_stream based clients (like Redis). So, yeah, MongoDB calls are still blocking inside Coroutines.

You can move those calls to Task Workers. Their use are exactly for cases like that where Swoole can't make the I/O non-blocking: https://wiki.swoole.com/#/start/start_task

Draghmar commented 2 years ago

Yeah, I was afraid is going to be something like this. I was hoping that this blocking nature won't be so troublesome when I'll do what I was trying to do but it seems it's still an issue.

I was trying the Task approach but those aren't available at WorkerStart where I have Tick defined. Unless there's a way to start Task manually within each Tick context?

Draghmar commented 2 years ago

I still can't find this repo that had some trick about getting MongoDB working with more then one connection at once. I know I've seen it somewhere...:(

Edit: Few minutes after sending this message I've manage to finally find it. :P Now I need to check if that's something that can be used for something more then simple test.