5

I'm trying to increase the allowed memory for certain PHP script. No matter what I do, for instance this:

ini_set('memory_limit', '512M');

... the script always runs out of memory at around 300MB:

Fatal error: Out of memory (allocated 25165824) (tried to allocate 343810589 bytes) in \\Foo\phpQuery\phpQuery.php on line 255

I've verified by several means that memory_limit is actually changed. The issue seems to be that PHP can't physically allocate a total of 300 MB of memory (25165824 bytes + 343810589 bytes = 352 MB).

I've tried both PHP/5.3.0 and PHP/5.3.9 in two different Windows-based computers with the following specs:

  • Windows XP / Windows Server 2003 (both computers are 32-bit boxes with 1GB or RAM)
  • Official PHP 32-bit VC9 binaries
  • Running as Apache 2.2 module (third-party 32-bit VC9 binaries)

I understand that using half of the physical RAM will force swapping and slow things down as hell but I just need to make sure the script actually works so it can be deployed to the live server. I've also tried larger values (which procuded the same error) and smaller values (with either made my script hit the limit or made Apache crash).

What can be the source of this apparently hard-coded memory limit?

Update #1: I've done further testing with the Windows Server 2003 box (which is actually a VMWare virtual machine). I've increased the "physical" RAM to 2 GB and I've verified that the paging file is allowed to grow up to 1152 MB. Task manager shows that current transaction load is 886 MB and there're 1,5 GB of free physical memory. However, I'm getting the same error with exactly the same figures.

Update #2: As I said, the memory_limit directive is fine. It shows up in both ini_get() and phpinfo(). The error message you'd get is slightly different from mine; mine indicates a PHP crash. Please compare:

Out of memory (allocated 25165824) (tried to allocate 343810589 bytes)
Allowed memory size of 25165824 bytes exhausted (tried to allocate 343810589 bytes)

I'll try to compose a script to reproduce the issue and report back.

Álvaro González
  • 142,137
  • 41
  • 261
  • 360
  • If PHP is trying to grab that much memory in one go, then I assume you're trying to load a file.... try loading the file in chunks rather than in one go – Mark Baker Jan 31 '12 at 11:17
  • «If you can't optimize, buy more RAM...» Well, some time it's wrong... ; ) Are you sure you need all that memory? 300MB is a huge amount already. Maybe you can optimize your script a bit... – Macmade Jan 31 '12 at 11:17
  • 2
    Are you 100% certain the OS has more than 300MB free memory to allocate? – DaveRandom Jan 31 '12 at 11:17
  • May be it would be better to run this script in CLI? Apache may be have some limits for memory, allocatable by modules – Timur Jan 31 '12 at 11:27
  • 1) Yes, I do need all that RAM because I'm performing in-memory XML manipulation and at this point of the project I can't afford to change the underlying XML library to use a pull parser. 2) No, I don't know if the OS has more than 300MB to allocate and I don't really know how to verify it. – Álvaro González Jan 31 '12 at 11:29
  • Only 1GB of RAM on the box? And running XP? Seems likely there really aren't enough megs left ;) – Lightness Races in Orbit Jan 31 '12 at 11:38
  • Is this something that you could practically provide a full source for so we can test it ourselves? – DaveRandom Jan 31 '12 at 12:00
  • have you tried to modify the php.ini memory limit? Cuz, php use different php.ini files for cli and cgi mod; more, try to check http://lv.php.net/manual/en/function.posix-getrlimit.php and more.. you always can install xdebug and take a look what excacly use more ram; i'm sure you can avoid using so much ram; – pomaxa Jan 31 '12 at 12:20
  • Check phpinfo() to make sure the change took place. Did you restart the web server? Is the php.ini file mentioned in there the one you modified? – Louis-Philippe Huberdeau Jan 31 '12 at 12:28

3 Answers3

4

An OOM exception is different to the memory limit warninigs.

This means PHP can't actually allocate the memory because insufficient resources are available within your operating system.

You'll need to check the system has sufficient memory/paging available to support this.

Paul Bain
  • 4,364
  • 1
  • 16
  • 30
0

Try with max_input_time, sometimes when PHP says memory_limit it actually means max_input_time (-1 is infinite for this one).

R01010010
  • 5,670
  • 11
  • 47
  • 77
  • Good point. But the value is already set to 20 minutes and the crash happens earlier. I haven't worked on this since I made the question but I know that sooner or later I'll need to fix the code so it doesn't need so much memory in the first place. – Álvaro González May 09 '13 at 10:16
  • Uhmm then i can't help anymore sorry! – R01010010 May 09 '13 at 10:20
0

I had a similar problem with out-of-memory errors popping up at numbers as low as 250MB. If you find your apache config file that controls ThreadsPerChild (for me it was /conf/extra/httpd-mpm.conf) and reduce the ThreadsPerChild from 150 to 50 or so under you should see a noticeable improvement... here's a script to test it out:

echo "Memory limit: ".ini_get("memory_limit")."<br><br>";
$a=array();
if (ob_get_level() == 0) ob_start();
for($i=0;$i<200;$i++)
{
    $a[]=str_pad('',1024*1024*32);
    echo "Pass ".$i.", memory used: ".number_format((memory_get_usage())/(1024*1024),0)." MB<br>";
    ob_flush();
    flush();
}
Peter Kionga-Kamau
  • 6,504
  • 2
  • 17
  • 13