Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
180 views
in Technique[技术] by (71.8m points)

Fatal error: Out of memory, but I do have plenty of memory (PHP)

Since my question is getting longer and longer, I decide to re-write the whole question to make it better and shorter.

I run my website on dedicated server with 8GB memory. I am fully aware that I need to raise the memory limit on php.ini setting. I have set it from 128M to 256M and to -1. Still the problem is persistence.

Fatal error: Out of memory (allocated 786432) (tried to allocate 24576 bytes) in D:wwwfootballviewsmain.php on line 81

The out of memory does not make sense because it said only 786432 bytes is allocated and it needed 24576 bytes more.

786432 bytes is only 768 kilobytes and is fairly small.

Hints

  • The error occurs on a very random line. It does not always error on line number 81.
  • At peak time, Apache only takes around 500mb of memory. I still have 6GB to spare.
  • There is no infinite loop.
  • The script takes 1,042,424 bytes. Getting this number from echo memory_get_peak_usage();
  • The resultset from MySQL is small (at most 12 of rows, purely text, no blob data)
  • (Important) If I restart Apache once every two days, the error is gone. It usually happens when Apache is running more than 2 days.
  • I have included the profiling the script and you can get it here.
  • This dedicated server is purely used to run only one website. This website is a high traffic website with average of 1,000 visitors every minute. At peak time, there will be 1,700 to 2,000 visitors accessing at the same time.

Server Spec

OS: Windows 2008 R2 64-Bit
CPU: Intel Core i5 - 4 cores
RAM: 8 GB
Apache 2.2
PHP 5.3.1
Storage: 2 x 1 TB hard drives
Bandwidth: 10 TB per month

Solution

I have finally tuned up and fixed the problem and I would like to share it here what I have done to improve:

  1. favicon.ico was missing which mess up with my route engine. Although my route engine is very small, but by including favicon.ico, it helps reduce memory usage by not running my route engine. Most of part of my website has it and I forgot to put it for this new section.
  2. Limit MaxRequestPerChild helps. In my other dedicated server, I have my MaxRequestPerChild limited. For this server, I set it to 0. I always thought that each script is isolated. Lets say if my script takes 800kb to run. Upon its completion, Apache or PHP should free 800kb memory. It seem like it doesn't work this way. Limited MaxRequestPerChild does help to prevent memory leak by creating new process after limited MaxRequestPerChild and the old process is dying. This is my new setting.

    ThreadsPerChild      1500
    MaxRequestsPerChild  10000 
    
  3. ob_flush(); does reduce slightly more memory. It does not help much but every bit of optimization helps.

  4. I have used xdebug which I have never used before as suggested by people who attempt to answer this question. I have to say it is great tool and I have optimized a few stuffs to make it run slightly faster.
  5. I have disable a few unnecessary Apache module. I am trying to disable it one by one and leave it a few days test to ensure it works perfectly before I disable another one. I do have all unnecessary PHP extension disable now.
  6. Most of my script in this server used traditional way (no template, no database layer, pure PHP, HTML, and legacy mysql_* function). To be honest, it runs very fast and used extremely small memory. However, maintenance the script is not very easy as the website is getting longer. I have tried to convert some parts of the website into proper framework (my own tiny framework). The reason that I used my own framework because it is tiny (3kb for the whole framework and include only what I need).
  7. Switching to IIS7.5 solving this problem completely.
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

I ran accross the same kind of problem with the server dying when trying to use the swap. This is because mod_php does not free memory ever. So Apache processes keep growing either reaching apache or PHP's memory limit or, if there's no limit, crashing the server.

Restarting apache makes it to spawn new fresh slim processes but as they run PHP scripts over time, they grow until problems arise.

The solution is to make apache to kill processes after a certain number of queries served so it will create new ones ( There are some questions related to that) reducing the MaxRequestsPerChild configuration option to, let's say 100 (Defaults to 1000).

Of course this may reduce server performances as it takes ressources to kill and spawn new processes but at least it keeps the site working. You might be tempted to raise the number of running processes to keep performances high, be sure PHP (or apache) memory limit x max number of processes do not get over your server's physical ram.

Here's my experience, hope it helps.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

2.1m questions

2.1m answers

60 comments

57.0k users

...