Once upon a time a web programmer who was writing a complicated script. He tests it in his machine, and it works like a charm. Then he tries in the production server…
Craaash. And not even a trace of error. He checks that error logging is on, checks the logs, nothing. He is “without a trace”… or a core dump… or anything.
My psychic powers tells me that is a memory error.
This kind of errors are typical when you are using a thousands-lines report or sending a heavily attachment loaded mail via php. In fact, the last reason make me write this post. I detected a hard to find problem with a very well known email script. Specifically the error I found was in a bad use of the chunk_split function, which just refuses to work with very very long string and dies miserably with out even send any kind of error (at least in older versions of php which I’m forced to use :S, but that’s another history).
Usually PHP captures this kind of errors and throws the typical error “Allowed memory size of x bytes exhausted”. This is caused because the server’s admin limited the memory that any script can use and was made to protect the servers against bad programmers, and is used commonly in shared environments.
To be able to handle this kind of problems, here is some basic tips to make this experience a lot less painful.
- Check your script’s memory usage
The memory_get_usage function returns the bytes used by your script. But this function is not available in every system, just in those which were compiled with the –enable-memory-limit option. Usually if this function is not available, you can’t either recompile your php installation. If this is the case, you can emulate the function with this code:
if( !function_exists('memory_get_usage') ){
function memory_get_usage() {
exec("ps -orss -p ".getmypid(), $output);
return $output[1];
}
}
This function is similar to the one included in php, even if is not perfect. But you can get an idea of what’s going on. Requires you have execution privileges because uses the ps command. It just works on Unix or Linux systems.
- When you are done, don’t forget to clean-
If you are not longer use a memory intensive variable, destroy it with unset($variable). This will free up the used memory.
- Say no to globals.
This is an extension from the last one. Be careful when you use global variables. When you use unset a global variable inside a function. you will just destroy the local variable, not the global one. So, you have one more reason to NOT use global variables (as if you need one more
)
- Don’t trust the garbage man!
I’ve noticed than when a function ends, local variables are unset. Although that is not always the case, sometimes even when the variables are unset, the memory doesn’t becomes available until the end of the script. So when you use heavy variables inside a function, unset em before the function ends if you will not longer use em.
- Forget as soon as you can.
If you are using a very long archive, don’t keep it in memory. That would be the easy way but it will give you some problems later. Instead process the file line by line and write the result in a temp file. tmpfile, fopen and fclose (and google
) are your friends. This will be the most useful advice for this cases, trust me.
- Don’t ignore the warnings
As a general recommendation, when you are debugging scripts, use error_reporting(E_STRICT). That will give you a little more information than E_ALL. As times goes by, you won’t note the difference between those two.
- Brute force
As a last resource, if those last advices doesn’t work (but they will
) you can make bigger the script memory limit, with the ini_set(“memory_limit”, “16M”) directive which would make the limit 16Mb. This directive is available with any server that allows the ini_set function. But be careful, especially if your are on a shared server, be a good neighbor and don’t blow the server. Don’t ask for free problems
This are some basic advices for those hard problems. If you people like this article, I could make some more deeper articles on the subject.