I want to ask you, in PHP if I created a new class in a function, will the memory freed in the end of the function?
For example: Class
class config
{
var $mapProp = array("x"=>4333, "y"=>3520, "w"=>128, "h"=>128);
var $gameProp = array("maxLevel"=>14, "tilesSize"=>256);
var $mapUrl = 'map_files';
function getMapProp()
{
return $this->mapProp;
}
function getGameProp()
{
return $this->gameProp;
}
function getMapUrl()
{
return $this->mapUrl;
}
}
$config = new config();
and the function
class framework
{
function getUserMap()
{
require("class/config/config.php");
require("class/imageManipulation/image.php");
$mapUrl = $config->getMapUrl();
$x = $_GET['x'];
$y = $_GET['y'];
$level = $_GET['level'];
$main_img = $mapUrl.'/'.$level.'/'.$x.'_'.$y.'.jpg';
//Create a new class
$image = new imageManipulation();
//Set Up variables
$image->setProp($config->getMapProp());
$image->setGameProp($config->getGameProp());
return $image->getImage($main_img, $level, $x, $y);
}
}
$framework = new framework();
require("class/framework/framework.php");
$path = $_GET['path'];
switch ($path) {
case 'usermap':
$framework->getUserMap();
break;
}
in the getUserMap I have used two classes. One of them is the $config class the other is the $image class, after the end of the function will the memory used for this two classes be freed?
All the best,
Robert.
Yes it does. Local variables are disposed at the end of the function call. And if one of these local variables was an object, it is no longer referenced. Therefore it will get freed by the garbage collector.
Run a test on your exact case to find out:
<?php
class bar
{
public function __construct()
{
$this->data = str_repeat('x', 10000000);
}
}
function foo()
{
$b = new bar();
echo memory_get_usage()."\n";
}
echo memory_get_usage()."\n";
foo();
echo memory_get_usage()."\n";
?>
I get:
635248
10635960
635312
Which would indicate it does.
Obviously here nothing is referencing that data any more, so PHP is able to free it.
Firstly, I think you should describe exactly what you mean by "at the end of the function", do you mean at the end of a function call, or ... ?
PHP stores the function in the memory as a construct if you will, un-executed code, then when the function is executed depending on what the function is actually doing, memory is allocated.
For instance, if i had the following function:
function test()
{
$data = array();
for($i = 0; $i < 10000; $i++)
{
$data[] = array('one','two','three','four','five','six',);
}
}
the function is called and a reference to the memory is created for the array, each time you iterate the loop, the memory increases.
The function then ends's but if you notice the the data is not return, this is because the local variable is only available for that current scope, there for it would no longer be used and the garbage collector cleans out the memory.
So yes, it does clean out the allocated memory at the end of a function call.
A little tip (does not apply to objects in PHP 5).
you can pass data by references, so that your only modifying the same allocated memory regardless of the function,
for example:
/*
Allocate the string into the memory into
*/
$data = str_repeat("a",5000);
function minip(&$data)
{
$_data &= $data;
$_data = '';
}
im passing the point to the $data to a new variable, which just points to the old one, this way you can pass data around without making the garbage collector use more resources.
Related
The example in the php documentation on Closure::bind include static on the anonymous function declaration. why? I can't find the difference if it is removed.
with:
class A {
private static $sfoo = 1;
}
$cl1 = static function() { // notice the "static"
return self::$sfoo;
};
$bcl1 = Closure::bind($cl1, null, 'A');
echo $bcl1(); // output: 1
without:
class A {
private static $sfoo = 1;
}
$cl1 = function() {
return self::$sfoo;
};
$bcl1 = Closure::bind($cl1, null, 'A');
echo $bcl1(); // output: 1
I beg to differ. It's true that often it won't matter. But sometimes it matters a whole lot.
The closure holding a reference to $this might prevent garbage collection of that object, which in turn may also impact performance significantly. Here's an example where it really makes a huge difference:
class LargeObject {
protected $array;
public function __construct() {
$this->array = array_fill(0, 2000, 17);
}
public function getItemProcessor(): Closure {
// Try with and without 'static' here
return static function () {
// do some processing unrelated to $this
};
}
}
$start = microtime(true);
$processors = [];
for ($i = 0; $i < 2000; $i++) {
$lo = new LargeObject();
$processors[] = $lo->getItemProcessor();
}
$memory = memory_get_usage() >> 20;
$time = (microtime(true) - $start) * 1000;
printf("This took %dms and %dMB of memory\n", $time, $memory);
Here's the output with a normal closure:
This took 55ms and 134MB of memory
Here's the output with a static closure:
This took 22ms and 1MB of memory
I tested this with PHP 7.3.19 on Debian Buster, so YMMV. Obviously this is a specially constructed example to demonstrate the difference. But things like this may happen in real applications as well. I started using Slevomat's SlevomatCodingStandard.Functions.StaticClosure sniff to remind me to always use static closures.
found the difference: you can't bind static closures to object, only change the object scope.
class foo { }
$cl = static function() { };
Closure::bind($cl, new foo); // PHP Warning: Cannot bind an instance to a static closure
Closure::bind($cl, null, 'foo') // you can change the closure scope
Static Closures, like any other static method, cannot access $this.
Like any other method, a non-static Closure that does not access $this will generally work in a static context.
As you've noticed, it doesn't really matter.
It's like using the static keyword on a class method. You don't necessarily need it if you don't reference $this within the method (though this does violate strict standards).
I suppose PHP can work out you mean the Closure to access A statically due to the null 2nd argument to bind()
I'm sure this question has been asked a thousand times, but i had trouble finding an answer i could understand or use anywhere.
In my project, i need to use my sql class and other misc classes, in alot of the classes. Then i'm qurious to know what's the best way performance wise to pass the objects.
Should i pass the objects to the classes construct as reference?
class MyClass {
private $_link;
function __construct(&$db) {
$this->_link =& $db;
}
}
or value..
class MyClass {
private $_link;
function __construct($db) {
$this->_link = $db;
}
}
or simply create a new object?
class MyClass {
private $_link;
function __construct() {
$this->_link = new DB();
}
}
If you are using PHP5+, in almost all cases, objects are passed by reference by default.
As objects are already passed "by reference" in PHP5+ then using & you would actually pass a "reference to a reference to an object" not just a simple "reference to an object". This can be critical because it will allow the function within its local scope to change the actual reference globally and potentially remove the object entirely. For example one would think that the following example of passing the object by ref and passing by "normally" is completely the same:
$aa = new stdclass;
$aa->aa = 1;
byRef($aa);
function byRef(&$aaa) {
$aaa->aa = 2;
}
var_dump($aa); // Outputs {aa:2}
$bb = new stdclass;
$bb->bb = 1;
byVal($bb);
function byVal($bba) {
$bba->bb = 2;
}
var_dump($bb); // Outputs {bb:2}
Judging by the output it looks the same. But is it a good practice? Depends what you wanted to do. Look at the same example where we destroyed the original reference and "deleted" the object:
$aa = new stdclass;
$aa->aa = 1;
byRef($aa);
function byRef(&$aaa) {
$aaa->aa = 2;
$aaa = 0; // We are changing $aa, not $aaa, because $aaa is just a reference
}
var_dump($aa); // Outputs int:0, $aa is not an object anymore
$bb = new stdclass;
$bb->bb = 1;
byVal($bb);
function byVal($bba) {
$bba->bb = 2;
$bba = 0;
}
var_dump($bb); // Outputs {bb:0}
The code speaks for itself. In some cases this is needed, in other this is critical. In my opinion unless you really know what are you doing do not pass by reference.
I was looking at the source for Drupal 7, and I found some things I hadn't seen before. I did some initial looking in the php manual, but it didn't explain these examples.
What does the keyword static do to a variable inside a function?
function module_load_all($bootstrap = FALSE) {
static $has_run = FALSE
It makes the function remember the value of the given variable ($has_run in your example) between multiple calls.
You could use this for different purposes, for example:
function doStuff() {
static $cache = null;
if ($cache === null) {
$cache = '%heavy database stuff or something%';
}
// code using $cache
}
In this example, the if would only be executed once. Even if multiple calls to doStuff would occur.
Seems like nobody mentioned so far, that static variables inside different instances of the same class remain their state. So be careful when writing OOP code.
Consider this:
class Foo
{
public function call()
{
static $test = 0;
$test++;
echo $test . PHP_EOL;
}
}
$a = new Foo();
$a->call(); // 1
$a->call(); // 2
$a->call(); // 3
$b = new Foo();
$b->call(); // 4
$b->call(); // 5
If you want a static variable to remember its state only for current class instance, you'd better stick to a class property, like this:
class Bar
{
private $test = 0;
public function call()
{
$this->test++;
echo $this->test . PHP_EOL;
}
}
$a = new Bar();
$a->call(); // 1
$a->call(); // 2
$a->call(); // 3
$b = new Bar();
$b->call(); // 1
$b->call(); // 2
Given the following example:
function a($s){
static $v = 10;
echo $v;
$v = $s;
}
First call of
a(20);
will output 10, then $v to be 20. The variable $v is not garbage collected after the function ends, as it is a static (non-dynamic) variable. The variable will stay within its scope until the script totally ends.
Therefore, the following call of
a(15);
will then output 20, and then set $v to be 15.
Static works the same way as it does in a class. The variable is shared across all instances of a function. In your particular example, once the function is run, $has_run is set to TRUE. All future runs of the function will have $has_run = TRUE. This is particularly useful in recursive functions (as an alternative to passing the count).
A static variable exists only in a
local function scope, but it does not
lose its value when program execution
leaves this scope.
See http://php.net/manual/en/language.variables.scope.php
To expand on the answer of Yang
If you extend a class with static variables, the individual extended classes will hold their "own" referenced static that's shared between instances.
<?php
class base {
function calc() {
static $foo = 0;
$foo++;
return $foo;
}
}
class one extends base {
function e() {
echo "one:".$this->calc().PHP_EOL;
}
}
class two extends base {
function p() {
echo "two:".$this->calc().PHP_EOL;
}
}
$x = new one();
$y = new two();
$x_repeat = new one();
$x->e();
$y->p();
$x->e();
$x_repeat->e();
$x->e();
$x_repeat->e();
$y->p();
outputs:
one:1
two:1
one:2
one:3 <-- x_repeat
one:4
one:5 <-- x_repeat
two:2
http://ideone.com/W4W5Qv
static variable in a function means that no matter how many times you call the function, there's only 1 variable.
<?php
class Foo{
protected static $test = 'Foo';
function yourstatic(){
static $test = 0;
$test++;
echo $test . "\n";
}
function bar(){
$test = 0;
$test++;
echo $test . "\n";
}
}
$f = new Foo();
$f->yourstatic(); // 1
$f->yourstatic(); // 2
$f->yourstatic(); // 3
$f->bar(); // 1
$f->bar(); // 1
$f->bar(); // 1
?>
Inside a function, static means that the variable will retain its value each time the function is called during the life of the page load.
Therefore in the example you've given, if you call a function twice, if it set $has_run to true, then the function would be able to know that it had previously been called because $has_run would still be equal to true when the function starts the second time.
The usage of the static keyword in this context is explained in the PHP manual here: http://php.net/manual/en/language.variables.scope.php
I'm writing a simple linear linked list implementation in PHP. This is basically just for practice... part of a Project Euler problem. I'm not sure if I should be using unset() to help in garbage collection in order to avoid memory leaks. Should I include an unset() for head and temp in the destructor of LLL?
I understand that I'll use unset() to delete nodes when I want, but is unset() necessary for general clean up at any point?
Is the memory map freed once the script terminates even if you don't use unset()?
I saw this SO question, but I'm still a little unclear. Is the answer that you simply don't have to use unset() to avoid any sort of memory leaks associated with creating references?
I'm using PHP 5.. btw.
Unsetting references in PHP
PHP references tutorial
Here is the code - I'm creating references when I create $temp and $this->head at certain points in the LLL class:
class Node
{
public $data;
public $next;
}
class LLL
{
// The first node
private $head;
public function __construct()
{
$this->head = NULL;
}
public function insertFirst($data)
{
if (!$this->head)
{
// Create the head
$this->head = new Node;
$temp =& $this->head;
$temp->data = $data;
$temp->next = NULL;
} else
{
// Add a node, and make it the new head.
$temp = new Node;
$temp->next = $this->head;
$temp->data = $data;
$this->head =& $temp;
}
}
public function showAll()
{
echo "The linear linked list:<br/> ";
if ($this->head)
{
$temp =& $this->head;
do
{
echo $temp->data . " ";
} while ($temp =& $temp->next);
} else
{
echo "is empty.";
}
echo "<br/>";
}
}
Thanks!
Is the memory map freed once the script
terminates even if you don't use
unset()?
Yes - when a script ends, all of the memory resources allocated by it are freed.
I'm wondering if I can use a static variable for optimization:
public function Bar() {
static $i = moderatelyExpensiveFunctionCall();
if ($i) {
return something();
} else {
return somethingElse();
}
}
I know that once $i is initialized, it won't be changed by by that line of code on successive calls to Bar(). I assume this means that moderatelyExpensiveFunctionCall() won't be evaluated every time I call, but I'd like to know for certain.
Once PHP sees a static variable that has been initialized, does it skip over that line of code? In other words, is this going to optimize my execution time if I make a lot of calls to Bar(), or am I wasting my time?
I find it easier to do something like the code below. That way the caching is done globally instead of per implementation of the function.
function moderatelyExpensiveFunctionCall()
{
static $output = NULL;
if( is_null( $output ) ) {
//set $output
}
return $output;
}
static $i = blah() won't compile, because php doesn't allow expressions and function calls in static initializers. You need something like
function foo() {
static $cache = null;
if(is_null($cache)) $cache = expensive_func();
do something with $cache
}
This should work in your (quite simple) case:
function your_function() {
static $output;
if (!isset($output)) {
$output = 'A very expensive operation';
}
return $output;
}
As for a global caching mechanism, you may use a method similar to this one.
Here is quite shorter approach:
function stuff()
{
static $smthg = []; // or null, or false, or something else
if ($smthg) {
return $smthg;
}
// filling $smthg goes here
// with a lot of
// code strings
return $smthg;
}
How about:
if (!isset($i))
{
static $i = moderatelyExpensiveFunctionCall();
}