【问题标题】:Why am I getting memory leaks in SimplePie when using $item->get_permalink()?为什么我在使用 $item->get_permalink() 时会在 SimplePie 中出现内存泄漏?
【发布时间】:2023-03-15 07:35:01
【问题描述】:

我正在使用SimplePie 和 PHP 5.3(启用 gc)来解析我的 RSS 提要。这在执行以下操作时效果很好并且没有问题:

$simplePie = new SimplePie();
$simplePie->set_feed_url($rssURL);
$simplePie->enable_cache(false);
$simplePie->set_max_checked_feeds(10);
$simplePie->set_item_limit(0);
$simplePie->init();
$simplePie->handle_content_type();

foreach ($simplePie->get_items() as $key => $item) {
    $item->get_date("Y-m-d H:i:s");
    $item->get_id();
    $item->get_title();
    $item->get_content();
    $item->get_description();
    $item->get_category();
}

内存调试超过 100 次迭代(使用不同 RSS提要):

但是当使用$item->get_permalink() 时,我的内存调试看起来像这样超过 100 次迭代(使用 不同 RSS 提要)。

产生问题的代码

foreach ($simplePie->get_items() as $key => $item) {
    $item->get_date("Y-m-d H:i:s");
    $item->get_id();
    $item->get_title();
    $item->get_permalink(); //This creates a memory leak
    $item->get_content();
    $item->get_description();
    $item->get_category();
}

我尝试过的事情

  • 使用get_link 代替get_permalink
  • 使用提到的__destroy here(即使它应该在 5.3 中修复)

当前调试过程

我似乎已经将问题追溯到SimplePie_Item::get_permalink -> SimplePie_Item::get_link -> SimplePie_Item::get_links -> SimplePie_Item::sanitize -> SimplePie::sanitize -> SimplePie_Sanitize::sanitize -> SimplePie_Registry::call -> SimplePie_IRI::absolutize到现在为止。

我能做些什么来解决这个问题?

【问题讨论】:

    标签: php memory-leaks simplepie


    【解决方案1】:

    这实际上不是内存泄漏,而是没有被清理的静态函数缓存!

    这是由于SimplePie_IRI::set_iri(和set_authority,和set_path)。他们设置了一个静态的$cache 变量,但在创建SimplePie 的新实例时他们不会取消设置或清除它,这意味着变量只会越来越大。

    这可以通过改变来解决

    public function set_authority($authority)
    {
        static $cache;
    
        if (!$cache)
            $cache = array();
    
        /* etc */
    

    public function set_authority($authority, $clear_cache = false)
    {
        static $cache;
        if ($clear_cache) {
            $cache = null;
            return;
        }
    
        if (!$cache)
            $cache = array();
    
        /* etc */
    

    ..etc 在以下函数中:

    • set_iri,
    • set_authority,
    • set_path,

    SimplePie_IRI 中添加一个析构函数,使用静态缓存调用所有函数,在$clear_cache 中使用true 参数,将起作用:

    /**
     * Clean up
     */
    public function __destruct() {
        $this->set_iri(null, true);
        $this->set_path(null, true);
        $this->set_authority(null, true);
    }
    

    随着时间的推移,这不会导致内存消耗增加:

    Git Issue

    【讨论】:

    • 对 SimplePie 的拉取请求怎么样?
    • 当您使用它时,将静态变量从该函数中移除并移至该类,这样您就无需向与此无关的函数引入另一个可选参数。如果您只想能够从类函数中重置它,则可以将其设为私有静态。 +1 找出原因。
    • 嗨 h2oooooo 当我使用 php 5.2.17 时,您的解决方案似乎解决了我的问题。但是如果我将我的服务器与 5.3.28 一起使用,它似乎不起作用。这是可以预料的吗? (这个问题还有其他解决方案吗?)谢谢!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-09-19
    • 1970-01-01
    • 1970-01-01
    • 2011-08-07
    • 1970-01-01
    相关资源
    最近更新 更多