允许的内存大小致命错误;改进脚本

Allowed Memory Size Fatal Error; Improve Script

我有以下功能,returns 一个格式化的 table 给我显示查看该网站的浏览器列表。它是从 MySQL 数据库和用户代理中检索到的(我知道这不是完全可靠的,但在这个时间点它已经足够好了)。

但是;这个函数(和另一个从同一个用户代理执行操作系统的函数最大化我们的允许内存大小并抛出 PHP 致命错误。我将内存限制增加到 100 MB,然后检查了 memory_get_peak_usage() 和两个 运行 大约 56 MB。

我可以对这个函数(以及 os 没有包含但与这个函数非常相似的函数)做些什么来提高内存使用率吗?

function getBrowsers() {
    global $stats,$db;
    $overall = $db->select("SELECT * FROM `".$db->prefix."web_stats`");
    /*while($row = $db->get_row($overall)) {
        $table[] = $row["agent"];
    }
    echo "<pre>";
    print_r($table);
    echo "</pre>";*/
    $overall = $db->num_rows($overall);

    $browser_array = array(
                        'msie'      => 'Internet Explorer',
                        'firefox'   => 'Firefox',
                        'safari'    => 'Safari',
                        'chrome'    => 'Chrome',
                        'edge'      => 'Edge',
                        'opera'     => 'Opera',
                        'netscape'  => 'Netscape',
                        'maxthon'   => 'Maxthon',
                        'konqueror' => 'Konqueror',
                        'mobile'    => 'Handheld Browser',
                        'spider'    => 'Search Spider',
                        'AdsBot'    => 'Google AdsBot',
                        'bot'       => 'Bot'
                 );

    

    $data["total"] = 0;
    foreach($browser_array as $value => $key) {
        $count = $this->get_os($value);
        $data[$key] = $count;
        $data["total"] += $count;
    }
    
    //$data["Unkown"] = $overall - $data["total"];
    
    arsort($data, SORT_NUMERIC);
    $table = "
        <table  class='table table-no-more table-bordered table-striped mb-none'>
            <thead>
                <tr>
                    <th>OS</th>
                    <th>Hits</th>
                    <th>Percent</th>
                </tr>
            </thead>
            <tbody>";
    foreach($data as $key => $value) {
        if($key!="total" && $value > 0) {
            $percent = $this->calculateper($value, $overall);
            if(preg_match('/(Chrome)/i', $key) === 1) {
                $icon = '<i class="fab fa-chrome"></i>';                    
            }
            elseif(preg_match('/(FireFox)/i', $key) === 1) {
                $icon = '<i class="fab fa-firefox"></i>';                   
            }
            elseif(preg_match('/(Edge)/i', $key) === 1) {
                $icon = '<i class="fab fa-edge"></i>';                  
            }
            elseif(preg_match('/(Google)/i', $key) === 1) {
                $icon = '<i class="fab fa-google"></i>';                    
            }
            elseif(preg_match('/(Google)/i', $key) === 1) {
                $icon = '<i class="fab fa-google"></i>';                    
            }
            elseif(preg_match('/(bot)/i', $key) === 1) {
                $icon = '<i class="fas fa-robot"></i>';                 
            }
            
            elseif(preg_match('/(Internet Explorer)/i', $key) === 1) {
                $icon = '<i class="fab fa-internet-explorer"></i>';                 
            }
            
            elseif(preg_match('/(Spider)/i', $key) === 1) {
                $icon = '<i class="fas fa-spider"></i>';                    
            }
            
            elseif(preg_match('/(Opera)/i', $key) === 1) {
                $icon = '<i class="fab fa-opera"></i>';                 
            }
            elseif(preg_match('/(Safari)/i', $key) === 1) {
                $icon = '<i class="fab fa-safari"></i>';                    
            }
            else {
                $icon = '<i class="far fa-question-circle"></i>';
            }
            $table .= "<tr>
                <td data-title='OS'>
                    ".$icon." ".$key."
                </td>
                <td data-title='Hits'>
                ".$value."
                </td>
                <td data-title='Percent'>
                    <div class='progress dark m-md'>
                        <div class='progress-bar progress-bar-success' role='progressbar' aria-valuenow='".$percent."' aria-valuemin='0' aria-valuemax='100' style='width: ".$percent."%;'>
                            ".$percent."%
                        </div>
                    </div>
                </td>
                </tr>";
        }
    }
    $table .= '</tbody>
            </table>';

    return $table;
}
//Get counts from the user agent
function get_os($opers) {
    global $stats,$db;
    $sql = "SELECT count(agent) as cnt FROM `".$db->prefix."web_stats` WHERE `agent` LIKE '%$opers%'"; 
    $result = $db->select($sql); 
     while ($row = $db->get_row($result)) { 
        $os1 = $row["cnt"]; 
        return $os1;
     } 
} 

乍一看,您执行的第一个查询似乎使用了最多的内存,因为您在其中加载所有数据table只是为了稍后计算结果。

因此,第一个改进是让数据库进行计数,就像您已经为操作系统所做的那样:

$stmt = $db->select("SELECT COUNT(*) AS total FROM `".$db->prefix."web_stats`");
$result = $db->get_row($stmt);
$overall = $result['total'];

您应该考虑的第二件事是对代码进行一些格式化,因为我觉得它有点乱。