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.
Related
First of all - there seem to be many questions about the fundamentals of tick functionality, so I want to add the top user comment at php.net/declare to the pile for anyone looking for further information. I found it while digging around as I tried to figure out the following.
So, I'm working on writing a simple debug helper. I want to add function tracing and benchmarking - basically what tick functionality is perfect for.
Thing is, I want to enable and disable benchmarking depending on arbitrary conditions that occur during script processing. I'm not really looking for fixed debugging à la scoped declare() { ... }.
What I'm looking to do is to put declare(); at the top of my script, and then register and unregister my debugging/benchmarking (tick) function as appropriate. Un/registration won't happen (too) often, so is efficient and reasonable.
But then I got curious: when I don't have a tick function registered... does the fact that I've run declare(ticks=1); have any effect on execution efficiency? Does it cause any extra processing to become permanently enabled anyway?
Analysis of PHP(7)'s source code shows that the answer is technically yes, but I'm not yet sure how.
The answer seems to be in zend_compile.c:8200: it appears this function defers compilation processing to the appropriate routines, then if ticks are enabled it additionally emits a ZEND_TICKS opcode into the opline via zend_emit_tick() in :2167. The opcode reference page for TICKS seems consistent with this conclusion; it shows an example disassembled opcode listing which has TICKS opcodes scattered throughout it, and I was wondering how they got in there until I discovered the above.
The ZEND_TICKS handler (in zend_vm_def.h:6859) seems to call zend_ticks_function(). This is mapped to ticks_function() in zend.c:754, which is in turn mapped to php_run_ticks() in main.2013. This is finally defined in php_ticks.c, where it's all of:
void php_run_ticks(int count)
{
zend_llist_apply_with_argument(
&PG(tick_functions),
(llist_apply_with_arg_func_t) php_tick_iterator,
&count
);
}
Huh. Not bad.
But here's the thing. If I declare(ticks=1);, the above dispatch is being run for literally every statement executed. That's... ouch. For long-running scripts containing high-iteration-count, tight processing loops, I'm wondering how badly that'll add up.
Problem is, I'm not even sure how to benchmark this. The only way I could envisage to do so would be to synthesize some PHP bytecode and then figure out a way to inject that directly into the PHP bytecode interpreter.
And that leads to my question: how much of a performance impact does this additional dispatch have, in practice? How can I quantify it?
Obviously the above investigation was performed on the canonical PHP.net interpreter. I haven't looked into how HHVM does this at all (yet), but I wouldn't at all mind learning how it handles it.
When using spl_autoload_register(), if I understand correctly, once you run it, PHP saves it for every file.
The question I have, and this is really three questions, is:
How do you remove a function from spl_autoload_register()?
Does spl_autoload_register() save the functions to be autoloaded and restore them upon restarting php?
Does the function in spl_autoload_register() always run from the same location?
Go to php.net/spl_autoload_register. On the left side, under spl_autoload_register, it says spl_autoload_unregister.
It saves the autoloders every time the script runs (which is every time someone visits the page).
If I understand this question then, yes. If you tell it where to find something then it will always look there (unless you do something iffy).
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.
I was wondering, I have a few functions in PHP that're not called every time but still are included in my files on each load. Does it still run the code even if your not calling the function at that time? The reason I'm asking, the codes in my function are expensive to run CPU wise and I don't call them every time and want to make sure if there not called they do not run the code within the function.
Thank you
In short, a function that isn't explicitly called does not run. However, here is a short what and why we use functions that I found.
A function is a "black box" that we've locked part of our program
into. The idea behind a function is that it compartmentalizes part of
the program, and in particular, that the code within the function has
some useful properties:
It performs some well-defined task, which will be useful to other
parts of the program.
It might be useful to other programs as well; that is, we might be
able to reuse it (and without having to rewrite it).
The rest of the program doesn't have to know the details of how the
function is implemented. This can make the rest of the program
easier to think about.
The function performs its task well. It may be written to do a
little more than is required by the first program that calls it,
with the anticipation that the calling program (or some other
program) may later need the extra functionality or improved
performance. (It's important that a finished function do its job
well, otherwise there might be a reluctance to call it, and it
therefore might not achieve the goal of reusability.)
By placing the code to perform the useful task into a function, and
simply calling the function in the other parts of the program where
the task must be performed, the rest of the program becomes clearer:
rather than having some large, complicated, difficult-to-understand
piece of code repeated wherever the task is being performed, we have
a single simple function call, and the name of the function reminds
us which task is being performed.
Since the rest of the program doesn't have to know the details of
how the function is implemented, the rest of the program doesn't
care if the function is reimplemented later, in some different way
(as long as it continues to perform its same task, of course!). This
means that one part of the program can be rewritten, to improve
performance or add a new feature (or simply to fix a bug), without
having to rewrite the rest of the program.
Functions are probably the most important weapon in our battle against
software complexity. You'll want to learn when it's appropriate to
break processing out into functions (and also when it's not), and how
to set up function interfaces to best achieve the qualities mentioned
above: reuseability, information hiding, clarity, and maintainability.
http://www.eskimo.com/~scs/cclass/notes/sx5.html
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.