1

I have a relatively large PHP-codebase (thousands of lines) for an application built with CodeIgniter. To be able to trace preformance issues and to be able to generate statistics and such, the developement-servers run Xhprof. This works fine, provided that the script actually comes to the logging part.

However, I've now come at a situation where the script just times out. On the developement-servers, it just gives a timeout ("Server not found") error, and sometimes even crashes the Apache process. No Xhprof file is generated, the CodeIgniter logging system generates nothing. Error reporting IS enabeled.

On a live enviroment (well, mirror of the live-server), the application actually generates an error:

Fatal error: Allowed memory size of 33554432 bytes exhausted (tried to allocate 261900 bytes) in /home/www/application/system/database/drivers/mysql/mysql_driver.php on line 493

This, and having a clue on how to reproduce the error, gives me somewhat of a hunch where to start haunting for a solution. But it's a time consuming job to do.

I'm looking for a way to be able to trace WHERE the actual "memory leak" is happening. Instead of manually debugging line after line. Any suggestions are greatly appreciated.

UPDATE : THE LOW MEMORY OF THE SERVER IS NOT THE PROBLEM. On a developement-server with more memory, the same problem occurs. The problem was an infinite loop, allocating more memory then my server could handle. The question remains: how can these errors be tracked down quickly?

Zar
  • 6,786
  • 8
  • 54
  • 76
  • 3
    32MB isn't a whole lot of headroom, depending on what your application needs to do. Are you sure you don't simply need more memory to handle the data coming back from your DB? – Brad Aug 13 '12 at 23:16
  • @Brad I'm sure that I, somewhere, have a bad loop or similar which keeps allocating memory. Howerver, it's quite a job to track it down :-) – Zar Aug 13 '12 at 23:21
  • PHP doesn't leak memory, it has a garbage collector, any time a variable or object goes out of scope, it is subject to automatic garbage collection. But I agree with Brad, 32MB isn't very much memory. Just read up about [how large PHP arrays are](http://nikic.github.com/2011/12/12/How-big-are-PHP-arrays-really-Hint-BIG.html) and you'll see that even a small array can consume a lot of memory. – drew010 Aug 13 '12 at 23:21
  • Is line 493 of your `mysql_driver.php` script fetching results in a loop into an array? Likely you are putting "too many" results into an array. – drew010 Aug 13 '12 at 23:22
  • @drew010 I am aware of that, I was unable to find a more "suiting" word for my matter. It's absolutely an error with my code and not the servers settings. On a dev server with tons of more memory, it still won't run. – Zar Aug 13 '12 at 23:24
  • Note that using more than 32 megs should hardly be considered a memory leak. Also, you might try [XDebug](http://xdebug.org/). – Lusitanian Aug 13 '12 at 23:24
  • Give yourself a little more memory for that one script, maybe? ini_set('memory_limit', '64MB'); – Matthew Blancarte Aug 13 '12 at 23:37
  • I actually, just by a lucky hunch and by viewing GIT commit history, found the error. A object treated like an array which caused a chain of queries against the database. Like said, the memory limit was not the problem. – Zar Aug 13 '12 at 23:44
  • Protip: if the script times out complaining about memory it's almost always a loop gone wrong :) – Mahn Aug 13 '12 at 23:53
  • the amount of memory available to the server may not be relevant. Individual processes have limits too, for good reason. – ddyer Aug 13 '12 at 23:54
  • Please check my edit to the OP. It was indeed a loop gone bad, but I am still looking for a way to find these problems faster in the future. – Zar Aug 13 '12 at 23:57
  • @Zar check out my answer below, it's probably the only way. – Mahn Aug 14 '12 at 00:04

2 Answers2

2

A common problem with programs that intend to keep statistics is that the keep pointers to everything they touch, which prevents the memory management from reclaiming them. If that's not the case, this probably isn't a leak, it's probably just a runaway allocation. You probably have only a few places that might be doing it. A good start is to replace direct calls to system functions that allocate chunks of memory with your own functions, then instrument those functions, looking for unexpectedly large array allocations.

The quoted limit (32mb) isn't very big by modern standards. It could easily be the case that there's nothing wrong except the process has an unreasonably low limit.

ddyer
  • 1,792
  • 19
  • 26
2

Use xdebug. As opposed to xhprof, profiling with xdebug produces output as the script runs which means even if the script hangs or times out you will be able to dissect the trace generated up to that point.

See also Profiling with xdebug to get started.

Mahn
  • 16,261
  • 16
  • 62
  • 78
  • @Zar no problem, note that xdebug doesn't have a web interface, which can seem odd at first, but tools like KCacheGrind on Linux or WinCacheGrind on win give a great interface to the output of xdebug. – Mahn Aug 14 '12 at 00:29