繁体   English   中英

while循环中的php性能问题

[英]php performance issue in while loop

我使用PHP来进行纬度/经度点以生成JS并在OSM Map上显示点。 当我在录音中有10分钟或更长时间的暂停时,我想在地图上制作一首新曲目。

我的数据集目前在大约10个不同的轨道上有大约30000条记录(一些轨道有大约300个点,其他轨道有数千个)。

我遇到了PHP的性能问题。 当循环聚集了数百个点时,数据的处理速度很快,但如果轨道有数千个点,则性能会急剧下降。

以下是每个轨道的每个点所需的时间

+-----------------+------------------------------+
| Points On Track | Time To Proceed 10000 Points |
+-----------------+------------------------------+
|              21 | 0.75                         |
|           18865 | 14.52                        |
|             539 | 0.79                         |
|             395 | 0.71                         |
|             827 | 0.79                         |
|             400 | 0.74                         |
|             674 | 0.78                         |
|            2060 | 1.01                         |
|            2056 | 0.99                         |
|             477 | 0.73                         |
|             628 | 0.77                         |
|             472 | 0.73                         |
+-----------------+------------------------------+

我们可以看到,当我在赛道上有很多分数时,表现会大幅下降。 在这种特殊情况下,处理所有点需要大约30个秒。 如果我将每个曲目的点数限制为500点,那么表现相当不错(我的数据集大约需要2.5秒)。

我使用Synology DS415play作为网络服务器。

这是我的代码:

$dataTab = array();
if ($result = $mysqli->query($sql)) 
    {   
        $count = 0;

        $row = $result->fetch_array();
        $data = $dataTab[$tabPrt] . "[" . $row['latitude'] . "," . $row['longitude'] . "]," ;
        $date = new DateTime($row['time']);         

        while($row = $result->fetch_array())
        {
            $count++;

            $newDate = new DateTime($row['time']);
            if(($newDate->getTimestamp() - $date->getTimestamp()) > 600)
            {
                array_push($dataTab, $data);
                $data= "";
                $count = 0;
            }

            $data = $data . "[" . $row['latitude'] . "," . $row['longitude'] . "]," ;
            $date = $newDate;
        }
        array_push($dataTab, $data);
    }

如果我将每首曲目限制在500点,那么表现非常好

$dataTab = array();
    if ($result = $mysqli->query($sql)) 
        {   
            $count = 0;

            $row = $result->fetch_array();
            $data = $dataTab[$tabPrt] . "[" . $row['latitude'] . "," . $row['longitude'] . "]," ;
            $date = new DateTime($row['time']);         

            while($row = $result->fetch_array())
            {
                $count++;

                $newDate = new DateTime($row['time']);
                if(($newDate->getTimestamp() - $date->getTimestamp()) > 600  
                    || $count > 500)
                {
                    array_push($dataTab, $data);
                    $data= "";
                    $count = 0;
                }

                $data = $data . "[" . $row['latitude'] . "," . $row['longitude'] . "]," ;
                $date = $newDate;
            }
            array_push($dataTab, $data);
        }

谢谢

编辑:我在这里提供了一个数据样本: http//109.190.92.126/tracker/gpsData.sql慢脚本: http//109.190.92.126/tracker/map.php通过分割每个轨道的正常执行速度(最多500分) ): http//109.190.92.126/tracker/map_split.php

谢谢

如果您在最糟糕的情况下从数据库中获取18000条记录,您可以将时间戳检查移动到查询中以显着降低它,看起来您正在做的就是查看是否有十分钟的间隙然后推送到一个数组可以在mysql级别完成,这样你每次都不会从数据库中获取18000行,只需要你需要的行。

如果你发布你的mysql查询,我们可以看看把它放在那里。

编辑:尝试将查询更改为:

SELECT time, latitude, longitude 
FROM gpsData 
WHERE  time >= '2015-09-01' 
AND provider = 'gps' 
ORDER BY time DESC

这是最终产品(它在Heroku上等待dyno启动) http://sove.herokuapp.com/gps/

解决方案背后的想法是在服务器端计算时间戳中的差异,并操纵数组中的数据。

脚本在我的MBP上完成0.278s,占用15.75MB内存, $ts最终输出是一系列路由(我总共得到7个)。

有很多优化,包括跳过相同的坐标点。 地图上的缩放界限不正确但你会弄清楚。 我应该真的要求获得这份工作的赏金......如果你喜欢结果然后让我知道,我可以分享代码库。

资料来源: https//gist.github.com/jpaljasma/04f54e0d2fa3a632071e

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM