I am very confused about how using & operator to reduce memories.
Can I have an answer for below question??
clase C{
function B(&$a){
$this->a = &$a;
$this->a = $a;
//They are the same here created new variable $this->a??
// Or only $this->a = $a will create new variable?
}
}
$a = 1;
C = new C;
C->B($a)
Or maybe my understanding is totally wrong.....
Never ever use references in PHP just to reduce memory load. PHP handles that perfectly with its internal copy on write mechanism. Example:
$a = str_repeat('x', 100000000); // Memory used ~ 100 MB
$b = $a; // Memory used ~ 100 MB
$b = $b . 'x'; // Memory used ~ 200 MB
You should only use references if you know exactly what you are doing and need them for functionality (and that's almost never, so you could as well just forget about them). PHP references are quirky and can result to some unexpected behaviour.
I am very confused about how using & operator to reduce memories.
If you don't know it, you probably don't need it :) The & is quite useless nowadays, because of several enhancements in the PHP-core over the last years. Usually you would use & to avoid, that PHP copies the value to the memory allocated for the second variable, but instead (in short) let both variables point to the same memory.
But nowadays
Objects are passed as reference anyway. They don't clone themself magically, because they are passed to a method ;)
When you pass primitive types, PHP will not copy the value, unless you change the variable (copy-on-write).
To sum it up: The benefits of & already exists as feature of the core, but without the ugly side-effects of the operator
Value type variables will only be copied when their value changes, if you only assign it in your example it wont be copied, memory footprint will be the same as if u have not used the & operator.
I recommend that you read these articles about passing values by reference:
When to pass-by-reference in PHP
When is it good to use pass by reference in PHP?
http://schlueters.de/blog/archives/125-Do-not-use-PHP-references.html
it is considered a microoptimalization, and hurts the transparency of the code
Related
In C++ if you pass a large array to a function, you need to pass it by reference, so that it is not copied to the new function wasting memory. If you don't want it modified you pass it by const reference.
Can anyone verify that passing by reference will save me memory in PHP as well. I know PHP does not use addresses for references like C++ that is why I'm slightly uncertain. That is the question.
The following does not apply to objects, as it has been already stated here. Passing arrays and scalar values by reference will only save you memory if you plan on modifying the passed value, because PHP uses a copy-on-change (aka copy-on-write) policy. For example:
# $array will not be copied, because it is not modified.
function foo($array) {
echo $array[0];
}
# $array will be copied, because it is modified.
function bar($array) {
$array[0] += 1;
echo $array[0] + $array[1];
}
# This is how bar shoudl've been implemented in the first place.
function baz($array) {
$temp = $array[0] + 1;
echo $temp + $array[1];
}
# This would also work (passing the array by reference), but has a serious
#side-effect which you may not want, but $array is not copied here.
function foobar(&$array) {
$array[0] += 1;
echo $array[0] + $array[1];
}
To summarize:
If you are working on a very large array and plan on modifying it inside a function, you actually should use a reference to prevent it from getting copied, which can seriously decrease performance or even exhaust your memory limit.
If it is avoidable though (that is small arrays or scalar values), I'd always use functional-style approach with no side-effects, because as soon as you pass something by reference, you can never be sure what passed variable may hold after the function call, which sometimes can lead to nasty and hard-to-find bugs.
IMHO scalar values should never be passed by reference, because the performance impact can not be that big as to justify the loss of transparency in your code.
The short answer is use references when you need the functionality that they provide. Don't think of them in terms of memory usage or speed. Pass by reference is always going to be slower if the variable is read only.
Everything is passed by value, including objects. However, it's the handle of the object that is passed, so people often mistakenly call it by-reference because it looks like that.
Then what functionality does it provide? It gives you the ability to modify the variable in the calling scope:
class Bar {}
$bar = new Bar();
function by_val($o) { $o = null; }
function by_ref(&$o) { $o = null; }
by_val($bar); // $bar is still non null
by_ref($bar); // $bar is now null
So if you need such functionality (most often you do not), then use a reference. Otherwise, just pass by value.
Functions that look like this:
$foo = modify_me($foo);
sometimes are good candidates for pass-by-reference, but it should be absolutely clear that the function modifies the passed in variable. (And if such a function is useful, often it's because it really ought to just be part of some class modifying its own private data.)
In PHP :
objects are passed by reference1 -- always
arrays and scalars are passed by value by default ; and can be passed by reference, using an & in the function's declaration.
For the performance part of your question, PHP doesn't deal with that the same way as C/C++ ; you should read the following article : Do not use PHP references
1. Or that's what we usually say -- even if it's not "completely true" -- see Objects and references
Does PHP provide any Lazy copy concept?
My believe is that Lazy copy is not implemented in PHP(infact is it a correct terminology?) while Lazy loading can be implement on object properties by simple flag property of an object.
I came across a answer(Please see) on SO with a large number of upvote, a part of explanation seems to be completely wrong.
He is saying unless $b is not changed $a will keep only reference of $b.
$b=3;
$a=$b;
// $a points to $b, equals to $a=&$b
$b=4;
// now PHP will copy 3 into $a, and places 4 into $b
I can understand Lazy loading. Keep a flag property in object and whenever we try to get the property of an object just initialize all properties from DB. Pseudo code looks like this:
private function GetAccessor($member) {
if($this->isLoaded != true) {
$this->Load(); //initialize or copy all properties from DB - LAZY LOADING
}
....
Note: php.net also doesn't mentioned lazy copy anywhere.
My believe is that Lazy copy is not implemented
It is implemented and it is called COW (Copy-on-Write)
See:
http://www.php.net/manual/en/features.gc.refcounting-basics.php (Example 3)
http://php.net/manual/en/internals2.variables.intro.php
Well yes PHP does this. This is an optimization strategy the php interpreter does for you. The concept is also known as "copy on write".
Suppose you have a reeeaaaallly large string
$a = "lllloooooong [imagine another million characters here]";
And then you want to copy that:
$b = $a;
Then chances are, that doing this copy operation was never necessary, because either you never altered $a or $b meaning that both variables have the same value at all the time and thus you could just use $a OR $b reducing your memory consumption by 50% and saving you that copy operation.
So the PHP-interpreter will on the first operation $b = $a assume, that you probably will never change $a or $b and it will not do any copying but instead it memorizes that $b has the same data as $a. As soon as you change $b or as soon as you change $a, the interpreter's previous assumption is proven as wrong and the interpreter will do the copying after all.
But this behaviour is an operation that happens behind the scenes. You don't see it, you can't influence it directly and it does not have any effect that you must be aware of in order to code PHP. Instead you can always work as if variables would be copied immediately.
In C++ if you pass a large array to a function, you need to pass it by reference, so that it is not copied to the new function wasting memory. If you don't want it modified you pass it by const reference.
Can anyone verify that passing by reference will save me memory in PHP as well. I know PHP does not use addresses for references like C++ that is why I'm slightly uncertain. That is the question.
The following does not apply to objects, as it has been already stated here. Passing arrays and scalar values by reference will only save you memory if you plan on modifying the passed value, because PHP uses a copy-on-change (aka copy-on-write) policy. For example:
# $array will not be copied, because it is not modified.
function foo($array) {
echo $array[0];
}
# $array will be copied, because it is modified.
function bar($array) {
$array[0] += 1;
echo $array[0] + $array[1];
}
# This is how bar shoudl've been implemented in the first place.
function baz($array) {
$temp = $array[0] + 1;
echo $temp + $array[1];
}
# This would also work (passing the array by reference), but has a serious
#side-effect which you may not want, but $array is not copied here.
function foobar(&$array) {
$array[0] += 1;
echo $array[0] + $array[1];
}
To summarize:
If you are working on a very large array and plan on modifying it inside a function, you actually should use a reference to prevent it from getting copied, which can seriously decrease performance or even exhaust your memory limit.
If it is avoidable though (that is small arrays or scalar values), I'd always use functional-style approach with no side-effects, because as soon as you pass something by reference, you can never be sure what passed variable may hold after the function call, which sometimes can lead to nasty and hard-to-find bugs.
IMHO scalar values should never be passed by reference, because the performance impact can not be that big as to justify the loss of transparency in your code.
The short answer is use references when you need the functionality that they provide. Don't think of them in terms of memory usage or speed. Pass by reference is always going to be slower if the variable is read only.
Everything is passed by value, including objects. However, it's the handle of the object that is passed, so people often mistakenly call it by-reference because it looks like that.
Then what functionality does it provide? It gives you the ability to modify the variable in the calling scope:
class Bar {}
$bar = new Bar();
function by_val($o) { $o = null; }
function by_ref(&$o) { $o = null; }
by_val($bar); // $bar is still non null
by_ref($bar); // $bar is now null
So if you need such functionality (most often you do not), then use a reference. Otherwise, just pass by value.
Functions that look like this:
$foo = modify_me($foo);
sometimes are good candidates for pass-by-reference, but it should be absolutely clear that the function modifies the passed in variable. (And if such a function is useful, often it's because it really ought to just be part of some class modifying its own private data.)
In PHP :
objects are passed by reference1 -- always
arrays and scalars are passed by value by default ; and can be passed by reference, using an & in the function's declaration.
For the performance part of your question, PHP doesn't deal with that the same way as C/C++ ; you should read the following article : Do not use PHP references
1. Or that's what we usually say -- even if it's not "completely true" -- see Objects and references
Before you tell me to read the manual, check out the php.net documentation for this function:
Warning
This function is currently not documented; only its argument list is available.
That was helpful!
This page explains that it enables garbage collection for cyclic references. Where and when is this useful? Could someone show me an example of its use? Preferably an example where a cyclic reference is created and then collected.
gc_enable is only needed if you call gc_disable. There is really no sane reason to do this, as that would cause cyclic references to not be garbage collected (like pre-5.3, when the cyclic GC did not exist).
PHP's garbage collector works by reference counting. You can think of a variable as a "pointer" to an object. When an object has no pointers to it, it is "dead" because nothing can reach it, so it is garbage collected.
//one thing points to the Foo object
$a = new Foo();
//now two things do
$b = $a;
//now only $b points to it
$a = null;
//now nothing points to Foo, so php garbage collects the object
$b = null;
Consider this though:
$a = new Foo();
$b = new Bar();
$b->foo = $a;
$a->bar = $b;
$a = $b = null;
At this point nothing is holding on to $a or $b except the objects themselves. This is a cyclic reference, and in previous versions of php (< 5.3), would not be collected. The cyclic collector in 5.3 can now detect this and clean up these objects.
There is a full chapter on Garbage Collection in the PHP Manual explaining this:
Reference Counting Basics
Collecting Cycles
Performance Considerations
I usually try not to just link offsite, but feel it's too much to summarize.
There are reasons why we use gc_disable and gc_enable.
In the latest PHP manual, it states
Can be very useful for big projects, when you create a lot of objects that should stay in memory. So GC can't clean them up and just wasting CPU time.
Issue in composer:
https://github.com/composer/composer/pull/3482#issuecomment-65199153
Solution and people replies:
https://github.com/composer/composer/commit/ac676f47f7bbc619678a29deae097b6b0710b799
Please be reminded that the second link above contains a lot of comments with graphics.
To begin with, I understand programming and objects, but the following doesn't make much sense to me in PHP.
In PHP we use the & operator to retrieve a reference to a variable. I understand a reference as being a way to refer to the same 'thing' with a different variable. If I say for example
$b = 1;
$a =& $b;
$a = 3;
echo $b;
will output 3 because changes made to $a are the same as changes made to $b. Conversely:
$b = 1;
$a = $b;
$a = 3;
echo $b;
should output 1.
If this is the case, why is the clone keyword necessary? It seems to me that if I set
$obj_a = $obj_b then changes made to $obj_a should not affect $obj_b,
conversely $obj_a =& $obj_b should be pointing to the same object so changes made to $obj_a affect $obj_b.
However it seems in PHP that certain operations on $obj_a DO affect $obj_b even if assigned without the reference operator ($obj_a = $obj_b). This caused a frustrating problem for me today while working with DateTime objects that I eventually fixed by doing basically:
$obj_a = clone $obj_b
But most of the php code I write doesn't seem to require explicit cloning like in this case and works just fine without it. What's going on here? And why does PHP have to be so clunky??
Basically, there are two ways variables work in PHP...
For everything except objects:
Assignment is by value (meaning a copy occurs if you do $a = $b.
Reference can be achieved by doing $a = &$b (Note the reference operator operates upon the variable, not the assignment operator, since you can use it in other places)...
Copies use a copy-on-write tehnique. So if you do $a = $b, there is no memory copy of the variable. But if you then do $a = 5;, the memory is copied then and overwritten.
For objects:
Assignment is by object reference. It's not really the same as normal variable by reference (I'll explain why later).
Copy by value can be achieved by doing $a = clone $b.
Reference can be achieved by doing $a = &$b, but beware that this has nothing to do with the object. You're binding the $a variable to the $b variable. It doesn't matter if it's an object or not.
So, why is assignment for objects not really reference? What happens if you do:
$a = new stdclass();
$b = $a;
$a = 4;
What's $b? Well, it's stdclass... That's because it's not writing a reference to the variable, but to the object...
$a = new stdclass();
$a->foo = 'bar';
$b = $a;
$b->foo = 'baz';
What's $a->foo? It's baz. That's because when you did $b = $a, you are telling PHP to use the same object instance (hence the object reference). Note that $a and $b are not the same variable, but they do both reference the same object.
One way of thinking about it, is to think of all variables which store an object as storing the pointer to that object. So the object lives somewhere else. When you assign $a = $b where $b is an object, all you're doing is copying that pointer. The actual variables are still disjoint. But when you do $a = &$b, you're storing a pointer to $b inside of $a. Now, when you manipulate $a it cascades the pointer chain to the base object. When you use the clone operator, you're telling PHP to copy the existing object, and create a new one with the same state... So clone really just does a by-value copy of the varaible...
So if you noticed, I said the object is not stored in an actual variable. It's stored somewhere else and nothing but a pointer is stored in the variable. So this means that you can have (and often do have) multiple variables pointing to the same instance. For this reason, the internal object representation contains a refcount (Simply a count of the number of variables pointing to it). When an object's refcount drops to 0 (meaning that all the variables pointing to it either go out of scope, or are changed to somethign else) it is garbaged collected (as it is no longer accessable)...
You can read more on references and PHP in the docs...
Disclaimer: Some of this may be oversimplification or blurring of certain concepts. I intended this only to be a guide to how they work, and not an exact breakdown of what goes on internally...
Edit: Oh, and as for this being "clunky", I don't think it is. I think it is really useful. Otherwise you'd have variable references being passed around all over the place. And that can yield some really interesting bugs when a variable in one part of an application affects another variable in another part of the app. And not because it's passed, but because a reference was made somewhere along the line.
In general, I don't use variable references that much. It's rare that I find an honest need for them. But I do use object references all the time. I use them so much, that I'm happy that they are the default. Otherwise I'd need to write some operator (since & denotes a variable reference, there'd need to be another to denote an object reference). And considering that I rarely use clone, I'd say that 99.9% of use cases should use object references (so make the operator be used for the lower frequency cases)...
JMHO
I've also created a video explaining these differences. Check it out on YouTube.
In Short:
In PHP 5+ objects are passed by reference. In PHP 4 they are passed by value (that's why it had runtime pass by reference, which became deprecated). So, you have to use the clone operator in PHP5 to copy objects:
$objectB = clone $objectA;
Also note that it's just objects that are passed by reference, not other variables. The following may clear you up more:
PHP References
PHP Object Cloning
PHP Objects and References
i've written a presentation to explain better how php manage memory with its variables:
https://docs.google.com/presentation/d/1HAIdvSqK0owrU-uUMjwMWSD80H-2IblTlacVcBs2b0k/pub?start=false&loop=false&delayms=3000
take a look ;)