Уменьшить утечки памяти в PHP-скрипте - PullRequest
0 голосов
/ 10 мая 2019

У меня есть скрипт php, который вызывается с помощью шорткода в WordPress.Некоторое время он работает нормально, но в конечном итоге приводит к сбою моего сервера.

Сам по себе скрипт занимает 3 Мб памяти (проверено с использованием get_memory_peak_usage)

Однако проблема возникает из-за того, чтошорткод, и его можно разместить в 3,4, даже 5 разных местах на одной странице.

Например, если я хочу, чтобы имя пользователя отображалось на панели навигации рядом с его аватаром, и даже иметьмаленькое сообщение "Welcome {username}" Мне нужно было бы поместить шорткод 3 раза.

Мне нужно уменьшить объем памяти, 1 запуск скрипта занимает почти ничего.

SOсамое первое, что я попробовал, когда сервер впервые вышел из строя, это освободить переменные, которые выглядят примерно так

Я создал функцию, которая устанавливает переменную в 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 Ответ

2 голосов
/ 10 мая 2019

Вот демоверсия , сделанная при загрузке нескольких аватаров (IE: аватары многих пользователей)

Вместо перезагрузки нескольких запросов (нескольких транзакций) для большого набора данных вы можете создать статический экземпляр и затем получить доступ к данным после него.

Вы можете достичь этого, создав черту для своего класса, которая будет использоваться следующим образом.

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, таким образом загружая данные только один раз, а затем создать метод получения для получения данных.

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 по умолчанию не передаются по ссылке, поэтому метод содержит аргументы в своей области видимости.

Чтобы этот метод работал, вы можете использовать & для передачи по ссылке. Демо

function destoryVar(&$var) { ... }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...