Is it necessary to free_result() a mysqli_result after being done working with it ?
Could not doing this mean a PHP application can have a memory leak ? Could this basically make a PHP application inefficient or poorly optimised ?
I understand PHP variables are cleared as soon as the script execution is finished therefore I don't see a valid reason to free_result() unless I worked with a query returning a huge resultset which is not the case so far.
Related
I'm going through the journey of bringing our dating web app up to date past PHP 7+
I have been updating the depreciated code and squishing errors as they've popped up, thanks to the help of this site, and has a question in regards to our depreciated __destruct() functions.
I searched my error I was getting thrown, and found this link on github that solved my issue: https://github.com/sajari/simple-linkedin-php/issues/4
So supposedly the destruct functions break after PHP 7, and commenting them out DID fix my issue, but it left me worried.
Edit: Destruct still works, its just how my dated code was trying to
use it
I have one specific instances of the destruct being called in one of our class files that builds a job request page based on what job a user queries from our database.
/** free up memory
$tmp->__destruct();
unset($tmp);
**/
From what I can tell, everything is working fine, but I wonder what the consequences of this are. Should I replace it with some newer memory cleanup method? This app is so dated, I wonder if this clean-up is even needed anymore, or intentionally put in to stop a memory leak. My boss doesn't seem to know either.
I'm new to PHP in a professional sense, and would like to make sure this update still allows the same level of speed and usability for our clients.
Another stackoverflow question asked here: Deletion of a PHP object; also unset() and __destruct
A user answered by saying that the values are already cleared by the complete execution of a script, BUT could be explicitly cleared to stop any unintentional references.
This just lead to more questions. When that user means script, do they mean the specific function call?
To wrap this up, lets say that destruct and unset call was to stop a memory leak, what is an equivalent replacement for it?
Thanks!
I want to personally mark this question answered for my own sake. It
was extremely helpful!
$tmp->__destruct();
unset($tmp);
You should never be calling destructors directly like this. Calling unset($tmp) by itself will indirectly cause the destructor to fire when the object is removed. So, this code actually causes the destructor to be called twice, which is almost certainly not what you want.
When that user means script, do they mean the specific function call?
No, they mean that one particular PHP execution, from the first line of the first file to the last line of the last file. At the end of execution, everything is automatically freed. In PHP, this execution run usually refers to one single short web request, so explicit calls to unset() for the sake of "freeing memory" are virtually never needed because an implicit unset() is going to happen as soon as the request is done. You'd only ever have to worry about doing this manually if, for example, the $tmp object uses a massive amount of memory at the start of a request, doesn't need it for the rest of the request, and runs for a long time. If you're just calling unset() at the end of the request, it's useless.
It's most likely safe to remove both these lines. The first is redundant and the second is almost never needed.
Note, it's much more likely to use unset() to remove a variable from scope than to free memory, so take care to scan if there's some code later on that needs $tmp to not exist.
Until recently I wasn't even aware it was possible for PHP to abort a script due to user disconnect.
Anyways, it could cause some real trouble for my database if the script could just abort midway through. Like if I'm inserting rows into multiple tables that partially depend on each other and only half of it gets done, I'd have to get real defensive with my programming.
Oddly enough, I found that ignore_user_abort defaults to false (at least on my installation), which seems like the sort of thing that could confuse the hell out of developers not aware of this possibility when something goes wrong because of it.
So to make things easier, shouldn't I just always set it to true? Or are there a good reason why it defaults to false?
Passing true to ignore_user_abort() as its only parameter will instruct PHP that the script is not to be terminated even if your end-user closes their browser, has navigated away to another site, or has clicked Stop. This is useful if you have some important processing to do and you do not want to stop it even if your users click cancel, such as running a payment through on a credit card. You can of course also pass false to ignore_user_abort(), thereby making PHP exit when the user closes the connection.
For handling shutdown tasks, register_shutdown_function() is perfect, as it allows you to register with PHP a function to be run when script execution ends.so it depends on your project
Anyways, it could cause some real trouble for my database if the script could just abort midway through. Like if I'm inserting rows into multiple tables that partially depend on each other and only half of it gets done, I'd have to get real defensive with my programming.
This can happen with or without ignore_user_abort, and should be addressed using database transactions.
So to make things easier, shouldn't I just always set it to true? Or are there a good reason why it defaults to false?
Since people are typically writing PHP code for the web, ignoring a user abort means your server would be sitting around doing useless work that's never going to be of value. Enough of them and you might find your server bogged down on abandoned, long-running HTTP requests.
If you've got lots of long-running requests that should ignore a user abort, a queue is a much better approach.
On big PHP sites, is there anything that should be done at the end of its script(s)?
For example, should mysqli_close() be called at the end? What is its purpose? What happens if it's not called?
Also, if during the script I assign a lot of data to a $variable, let's say 20 MB of plain text, should I unset the $variable at the end of the script, or is the data automatically "thrashed" when the script/request ends?
Is there anything else that should be usually done at the end of scripts?
during the script I assign a lot of data to a $variable, let's say 20 MB of plain text
You definitely should avoid such situations at all. With no exceptions. Especially on a big site.
I would sat 1Mb is max for the frontend script, but in practice 100K-200K should be enough.
For example, should mysqli_close() be called at the end? What is its purpose?
For example, you are supposed to ask a manual page for this question. Where you can learn that there is absolutely no point in calling this function at the end of script execution.
Using mysqli_close() helps free up database connections sooner, so it is good practice to use as soon as you no longer require the connection, though PHP does free this up as soon as a script has completed executing anyway.
As for unsetting variables or other kinds of cleanup, there really is no need. PHP collects garbage as and when the variables are no longer in use.
Question is, does it make sense, and how to, free memory and destroy / unset objects? Does exit() kill the app and nothing else has to be done?
In the manual, it states:
Terminates execution of the script. Shutdown functions and object destructors will always be executed even if exit() is called.
So it is sufficient to just call exit();
However, if you are using PHP to power a web app, calling of exit isn't necessary because php will showdown after the request is made and the response is returned.
It does make sense to use unset though in some cases when your dealing with a large quantity of objects that are getting left in memory while your script executes. If you do not cleanup after such methods you can hit the PHP memory limit set in php.ini which will terminate your script.
Things such as reading in files using file_get_contents can cause this too if you let the variable hang around that contains the file's contents.
It is rather rare though to see this occur, but best practice is to code for the future and clean up after yourself.
But back to the original question, no, PHP cleans everything up when the script terminates.
I am currently debugging a script that constantly runs into OutOfMemory exceptions. It is run as a cronjob and usually runs fine, but when the cronjob wasn't run for a while (for whatever reason) the script has to handle to many elements that queued up and will run into a OutOfMemory exception.
From examining the code I was not able to spot the problem. I believe one of the iterative function calls might leak memory, but I am not sure which one and where.
Is there an option to get PHP to dump the heap, when an OutOfMemory exception occurs? I might be able to spot the problem from there (most likely).
While I was not able to find a "dump heap on Exception" option, I did find get_defined_vars() which is basically a heap dump if called from a global scope. Using this I was able to see that there where hundreds (actually thousands) of still referenced database rows hanging around in my memory. This was due to a not freed mysql result resource somewhere in the infamous function that caused the leak. I found it and fixed it. It runs well now.
Well, easiest approach would be to use a try-catch block around that part of your script where the error possibly occurs and you will have to dump the stack in the catch part. The problem might be that the machine won't be able to react cause the memory is full and it terminates. I do not know if it helps to discard some variables to free up some memory to output some data.
EDIT: For this purpose use the php function debug-backtrace. This will give you a stack trace. So finding the error will be much likely in case the machine is still up.
Just do not load all objects together to memory, but read-as-you-process-them?
I've had lots of problems with simpleXML and memory leaks. They are a pain in the are to track down... took me days to figure out that simpleXML was causing then and then fix them.
As far as i know you cand programatically set a handled for OOM:)
Also, PHP's functions for displaying memory info fails to detect the memory leaks, i had scripts eating up ~1Gb of ram, but PHP's functions reported only 100Mb used:)
This is as good of a 'heap dump' as I'm able to quickly write in PHP. I take the defined variables and functions, then sort by their serialized length. Serialized length isn't a 100% reliable method for getting a variable's size, but it's pretty good, and generally useful for determining which objects are your memory hogs:
$memmap = array_map(function($var) { return strlen(serialize($var)); },
array_merge(get_defined_functions(), get_defined_vars()));
arsort($memmap);
var_dump($memmap);
You may want to tweak the callback function a bit if you'd like your results to be more verbose, or to recurse through the defined variables.
I've never seen PHP provide a native facility for this but a few other things might exist:
Try: https://github.com/mcfunley/php-heap/blob/master/php-heap.py
It could also be possible to write an extension to achieve the same.