4

I'm using SimplePie with PHP 5.3 (with gc enabled) to parse my RSS feeds. This works well and without problems when doing something like the following:

$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();
}

Memory debugging over 100 iterations (with different RSS feeds):

SimplePie without using get_permalink()

But when using $item->get_permalink(), my memory debugging looks like this over 100 iterations (with different RSS feeds).

Code to produce problem:

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();
}

SimplePie get_permalink memory leak

Things I've tried:

  • Using get_link instead of get_permalink
  • Using __destroy as mentioned here (even though it should be fixed for 5.3)

Current debugging process:

I seem to have traced the problem down to 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 as of now.

What can I do to fix this?

hakre
  • 193,403
  • 52
  • 435
  • 836
h2ooooooo
  • 39,111
  • 8
  • 68
  • 102

1 Answers1

9

This is actually not a memory leak, but rather static function caches that aren't being cleaned!

This is due to SimplePie_IRI::set_iri (and set_authority, and set_path). They set a static $cache variable, but they don't unset or clean this when a new instance of SimplePie is created, which means the variables only gets bigger and bigger.

This can be fixed by changing

public function set_authority($authority)
{
    static $cache;

    if (!$cache)
        $cache = array();

    /* etc */

to

public function set_authority($authority, $clear_cache = false)
{
    static $cache;
    if ($clear_cache) {
        $cache = null;
        return;
    }

    if (!$cache)
        $cache = array();

    /* etc */

..etc in the following functions:

  • set_iri,
  • set_authority,
  • set_path,

And adding a destructor to SimplePie_IRI calling all the functions using a static cache, with a parameter of true in $clear_cache, will work:

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

Which will now result in no gain in memory consumption over time:

SimplePie fixed

Git Issue

h2ooooooo
  • 39,111
  • 8
  • 68
  • 102
  • How about a pull request to SimplePie? – uzyn Feb 08 '13 at 03:36
  • And while you're at it, remove the static variable out of that function and move to the class so you don't need to introduce another optional parameter to a function this is unrelated to. You can make it a private static if you only want to be able to reset it from within class functions. +1 for finding out the cause. – hakre Mar 30 '13 at 07:23
  • Hi h2oooooo Your solution seems to solve my problem when I'm using php 5.2.17. But if I use my server with 5.3.28 it seems to not work. Is this to be expected? (is there another solution for this issue?) Thanks! – Tal Galili Dec 20 '14 at 07:09