json_decode - 如何在GuzzleHttp asnyc请求中加快速度

时间:2016-09-12 13:18:48

标签: php json guzzle

在我的应用程序中,我使用的是GuzzleHttp库,但这可能不是问题所在,但说出来并不好。

每分钟(使用cron)我需要从40多个地址获取数据,因此我尽可能快地使用GuzzleHttp lib。

Guzzle代码:

$client = new Client();
$rectangles = $this->db->query("SELECT * FROM rectangles");

$requests = function ($rectangles)
{
    foreach($rectangles as $rectangle)
    {
       // some GEO coords (It's not important)
       $left   = $rectangle["lft"];
       $right  = $rectangle["rgt"];
       $top    = $rectangle["top"];
       $bottom = $rectangle["bottom"];

       $this->indexes[] = $rectangle;

       $uri = "https://example.com/?left=$left&top=$top&right=$right&bototm=$bottom";
            yield new Request("GET", $uri);
   }

};

$pool = new Pool($client, $requests($rectangles), [
    'concurrency' => 5,
    'fulfilled' => function ($response, $index) {
        $resp   = $response->getBody();
        $carray = json_decode($resp,true);

        if($carray["data"] != null)
        {
            $alerts = array_filter($carray["data"], function($alert) {
                return $alert["type"] == 'xxx';
            });

            $this->data = array_merge($this->data, $alerts);
            $this->total_count += count($alerts);
        }
    },
    'rejected' => function ($reason, $index) {},
]);

$promise = $pool->promise();
$promise->wait();

return $this->data;

当然,我做了一个基准。

1. getting data from another server 0.000xx sec
2. json_decode 0.001-0.0100 (this is probably the problem :-()

整个代码大约需要6-8秒。它取决于远程服务器上的数据量。

我认为Guzzle一直以异步方式执行请求,因此需要时间作为最长的请求。

(最慢的请求= 200毫秒==所有请求= 200毫秒) - 但这可能不是真的!或者我做错了。

我在json_decode中使用了一个关联数组(我觉得这是1秒的加速度(我不确定......)。

我的问题是,我可以将此代码更优化并加快速度吗?

我希望以最慢的请求(0.200秒)快速完成。

PS:我从网址获取的数据只是长JSON。谢谢!

编辑:我改变了并发性' => 5到'并发' => 100,现在持续时间约为2-4秒

1 个答案:

答案 0 :(得分:1)

首先,将Pool配置中的concurrency值增加到您需要发送的请求总数。这应该没问题,实际上可能会让你更快。

关于以毫秒为单位加速json_decode,这可能取决于很多因素,包括您在处理JSON的服务器上使用的硬件以及不同大小的JSON数据。我不认为你可以用PHP编程来加速核心功能。我可能错了。

要查看的代码的另一部分是:$this->data = array_merge($this->data, $alerts);您可以尝试使用循环代替。

您还在使用array_filter执行双重工作,其中数组内部的数组在array_merge之前被迭代。

所以,而不是:

if ($carray["data"] != null) {
    $alerts = array_filter($carray["data"], function($alert) {
        return $alert["type"] == 'xxx';
    });

    $this->data = array_merge($this->data, $alerts);
    $this->total_count += count($alerts);
}

也许试试这个:

if ($carray["data"] != null) {
    foreach ($carray["data"] as $cdata) {
        if ($cdata["type"] == 'xxx') {
            $this-data[] = $cdata;
            $this->total_count++;
        }
    }
}