HOW TO: Exporting A LOT of Data (Out of Memory Issue)
-
I’m exporting a lot of data — thousands of users with hundreds of profile fields. It’s not ideal! And when I was doing so, I was running out of memory (limit set to 256M).
After a lot of debugging, I found that it was the WP non-persistent cache of BP objects that was filling up the memory. To fix it, I added the following (I added reference lines for context):
Around line 500, I added $memory_limit and I make sure that the output isn’t buffered (so it keeps spitting data into the file and downloads as fast as possible). Since the cache is what’s growing, I take a look to see if my PHP install is capable of overriding the core cache functions; if so, I blank them out so nothing new gets cached, just while the page is running:
ob_end_flush(); // no more buffering while spitting back the export data $memory_limit = $this->return_bytes(ini_get('memory_limit')) * .75; // we need to disable caching while exporting because we export so much data that it could blow the memory cache // if we can't override the cache here, we'll have to clear it later... if(function_exists('override_function')) { override_function('wp_cache_add', '$key, $data, $group="", $expire=0', ''); override_function('wp_cache_set', '$key, $data, $group="", $expire=0', ''); override_function('wp_cache_replace', '$key, $data, $group="", $expire=0', ''); override_function('wp_cache_add_non_persistent_groups', '$key, $data, $group="", $expire=0', ''); } elseif(function_exists('runkit_function_redefine')) { runkit_function_redefine('wp_cache_add', '$key, $data, $group="", $expire=0', ''); runkit_function_redefine('wp_cache_set', '$key, $data, $group="", $expire=0', ''); runkit_function_redefine('wp_cache_replace', '$key, $data, $group="", $expire=0', ''); runkit_function_redefine('wp_cache_add_non_persistent_groups', '$key, $data, $group="", $expire=0', ''); } //open doc wrapper.. echo $doc_begin; // echo headers ## echo $pre . implode( $seperator, $headers ) . $breaker;
Somewhere in the class, I added the function return_bytes:
function return_bytes($val) { $val = trim($val); $last = strtolower($val[strlen($val)-1]); switch($last) { // The 'G' modifier is available since PHP 5.1.0 case 'g': $val *= 1024; case 'm': $val *= 1024; case 'k': $val *= 1024; } return $val; }
Around line 570, where it echos each user row, I added:
// echo row data ## echo $pre . implode( $seperator, $data ) . $breaker; if(memory_get_usage() > $memory_limit) { wp_cache_flush(); } }
I’m not sure if the buffer line is necessary. But I can tell you that without the wp_cache_flush line I can’t export more than a few hundred of my users at a time before it runs out of memory. I wish I could clear just the BP stuff, but I didn’t see a way to do that. I weighed my options and decided that clearing my cache but being able to get data was more important than the time spent having to recreate whatever cache I just blew away. If you can come up with a better solution that isolates things, I’d love to hear about it!
I hope this helps.
-eli
- The topic ‘HOW TO: Exporting A LOT of Data (Out of Memory Issue)’ is closed to new replies.