减少PHP脚本中的内存泄漏

时间:2019-05-10 17:09:25

标签: php wordpress

我有一个WordPress脚本中的短代码调用的php脚本。它可以正常运行一段时间,但最终会导致服务器崩溃。

脚本本身占用3mb的内存(使用get_memory_peak_usage测试)

但是出现问题是因为它是一个简码,可以将其放置在一页上的3,4,甚至5个不同的位置。

例如,如果我想在导航栏中显示其头像旁边的用户名,并且甚至显示一条小信息“ Welcome {username}”,则必须输入3次简码。

我需要减少内存量1脚本的运行几乎不占用任何空间。

因此,服务器首次崩溃时我尝试的第一件事就是释放看起来像这样的变量

我创建了一个函数,将变量设置为null,然后取消设置

function DestroyVar($var){
    $var = null;
    unset($var);
}

然后我更新了我的代码,因此在使用完每一个代码之后,它都被“破坏了”。

function ParseUserAvatar($uid,$style = null){
            global $wpdb;

            $query = $wpdb->get_row("SELECT meta_value FROM wp_usermeta WHERE user_id=$uid AND meta_key='wp_user_avatar'");
      $result = $query->meta_value;

      mysqli_free_result($query);
      $this->DestroyVar($query);

            $decoded_data = unserialize($result);
      $this->DestroyVar($result);
            $src = $decoded_data[0]["avatar_url"];

            $this->DestroyVar($decoded_data);

            if(empty($src) || $src == null || $src == ''){
                $src = "https:////www.gravatar.com/avatar/24d7a56b7fbacec3ee5701d7ee5130e3?s=150&f=y&r=g";
            }

            $html = '';
            $html .= '
                <style>
                .dm-avatar-origin {
                    vertical-align: middle;
                    width: 212px;
                    height: 212px;
                    border-radius: 50%;
                }
                </style>
            ';

            if($style == null){
                $html .= '<img src="'.$src.'" alt="Avatar" class="dm-avatar-origin dm-avatar uap-member-photo">';
            }else{
                $html .= '<img src="'.$src.'" alt="Avatar" class="dm-avatar-origin uap-member-photo ' . $style . '">';
            }

            $this->DestroyVar($src);

            return $html;
        }

这并没有像我希望的那样减少内存使用量(50k-> 45k)

然后我开始减少创建的vars的数量,因此我的脚本现在看起来像这样

function ParseUserAvatar($uid,$style = null){
            global $wpdb;

            $query = $wpdb->get_row("SELECT meta_value FROM wp_usermeta WHERE user_id=$uid AND meta_key='wp_user_avatar'")->meta_value;

            $decoded_data = unserialize($query);
            mysqli_free_result($query);
            $this->DestroyVar($query);
            $src = $decoded_data[0]["avatar_url"];

            $this->DestroyVar($decoded_data);

            if(empty($src) || $src == null || $src == ''){
                $src = "https:////www.gravatar.com/avatar/24d7a56b7fbacec3ee5701d7ee5130e3?s=150&f=y&r=g";
            }

            $html = '';
            $html .= '
                <style>
                .dm-avatar-origin {
                    vertical-align: middle;
                    width: 212px;
                    height: 212px;
                    border-radius: 50%;
                }
                </style>
            ';

            if($style == null){
                $html .= '<img src="'.$src.'" alt="Avatar" class="dm-avatar-origin dm-avatar uap-member-photo">';
            }else{
                $html .= '<img src="'.$src.'" alt="Avatar" class="dm-avatar-origin uap-member-photo ' . $style . '">';
            }

            $this->DestroyVar($src);

            return $html;
        }

目前,我不知道如何进一步减少内存使用,并且仍然使服务器崩溃

1 个答案:

答案 0 :(得分:2)

  

在加载多个头像(即:许多用户头像)时,完成的操作demo

您可以创建一个静态实例,然后再访问该数据,而不是在大型数据集上重新加载多个查询(多个事务)。

您可以通过为类创建一个特征来实现此目的。

trait Singleton {
    private static $_instance;

    public static function getInstance() {
        # If the instance has already been created, use the object
        if(self::$_instance) return self::$_instance;

        # If this is a first time call, create the instance
        self::$_instance = new self();
        return self::$_instance;
    }

    protected function __construct() {}
    private function __clone() {}
}

然后,您可以简单地将数据加载到__construct回调中,从而仅加载一次数据,然后创建一个getter方法来检索数据。

class Avatar {
    use Singleton;

    private $_data;

    private function __construct() {
        /**
         * $this->_data = your query result (enter logic here)
         */
    }

    public function getData() { return $this->_data; }
}

现在要在页面上的任何地方显示它,您可以像下面这样简单地使用静态实例:

Avatar::getInstance()->getData()

由于在第一次调用后设置了$_instance,所以它总是返回带有生成数据的对象。仅对数据库进行了1次交易。

Ofc,这只是一个占位符。您将需要更新方法以包含所需的正确参数和逻辑。

更新

您的destoryVar方法无效。默认情况下,PHP变量不通过引用传递,因此该方法在其自己的范围内包含参数。

要使该方法有效,您可以使用&通过引用传递。 Demo

function destoryVar(&$var) { ... }