Or is everything reference counted with heap allocation? Since PHP has
escape analysis, this could be used to use the stack instead, and kill the
memory when the scope ends. If PHP uses the stack, can this be seen in the
opcode?
This stackoverflow thread does not really answer my question.
Olle
Or is everything reference counted with heap allocation? Since PHP has
escape analysis, this could be used to use the stack instead, and kill the
memory when the scope ends. If PHP uses the stack, can this be seen in the
opcode?
Well, you're not going to like this answer, but.... yes and no.
A single PHP call frame holds a block of storage space for (among other
things) all* local variables. This can be thought of analogously to "the
stack" as it's used by native applications. Basic scalars (null, bool,
int, float) sit in this space with no additional pointers to anywhere.
Non-scalars use pointers to elsewhere in the heap to store the actual
payload. This isn't unique to PHP, as these structures have runtime
determined size and thus can't** be stack allocated.
There's further asterii below all of those statements, but that's the
high-level generalized answer to your question as posed.
The implied question you asked is actually handled using another
mechanism. PHP's internals have two separate memory allocation pools.
"Persistent" memory allocation, which creates blocks of memory for the
lifetime of the process, and "Engine" memory allocation, which are bulk
de-allocated*** at the end of every request (after relevant
destructors have fired).
-Sara
- All variables which are explicitly references as $foo (excluding
auto-globals). ${'bar'} and $$baz style references to locals are special
and require their own separate conversation.
** C's alloca() and similar techniques in other languages can reserve
dynamic amounts of stack space, but let's ignore that power-move for the
sake of this argument.
*** Deallocated from the request handler's point of view, though the
runtime's memory manager (usually) doesn't give it back to the OS
immediately, since it's likely to be used by the next request anyway.
2021-01-03 16:15 GMT, Sara Golemon pollita@php.net:
On Fri, Jan 1, 2021 at 3:18 PM Olle Härstedt olleharstedt@gmail.com
wrote:Or is everything reference counted with heap allocation? Since PHP has
escape analysis, this could be used to use the stack instead, and kill
the
memory when the scope ends. If PHP uses the stack, can this be seen in
the
opcode?Well, you're not going to like this answer, but.... yes and no.
A single PHP call frame holds a block of storage space for (among other
things) all* local variables. This can be thought of analogously to "the
stack" as it's used by native applications. Basic scalars (null, bool,
int, float) sit in this space with no additional pointers to anywhere.
Non-scalars use pointers to elsewhere in the heap to store the actual
payload. This isn't unique to PHP, as these structures have runtime
determined size and thus can't** be stack allocated.There's further asterii below all of those statements, but that's the
high-level generalized answer to your question as posed.The implied question you asked is actually handled using another
mechanism. PHP's internals have two separate memory allocation pools.
"Persistent" memory allocation, which creates blocks of memory for the
lifetime of the process, and "Engine" memory allocation, which are bulk
de-allocated*** at the end of every request (after relevant
destructors have fired).-Sara
- All variables which are explicitly references as $foo (excluding
auto-globals). ${'bar'} and $$baz style references to locals are special
and require their own separate conversation.
** C's alloca() and similar techniques in other languages can reserve
dynamic amounts of stack space, but let's ignore that power-move for the
sake of this argument.
*** Deallocated from the request handler's point of view, though the
runtime's memory manager (usually) doesn't give it back to the OS
immediately, since it's likely to be used by the next request anyway.
Thanks Sara! I realize I should have been more precise: Can PHP
allocate non-reference counted memory that automatically is freed when
leaving scope, similar to what Go does with escape analysis?
Article describing the Go mechanism:
https://segment.com/blog/allocation-efficiency-in-high-performance-go-services/
Olle
Hi Olle,
Thanks Sara! I realize I should have been more precise: Can PHP
allocate non-reference counted memory that automatically is freed when
leaving scope, similar to what Go does with escape analysis?Article describing the Go mechanism:
https://segment.com/blog/allocation-efficiency-in-high-performance-go-services/
Could you give some concrete examples of what type of code you're talking about?
As Sara Golemon said, scalars (null, bool, int, float) are allocated on a php call frame,
and the call frames go on a stack. That stack is separate from the C stack, but still a stack
The call frame is "freed" when leaving scope - i.e. that part of the stack will be reused on subsequent calls.
A single PHP call frame holds a block of storage space for (among other
things) all* local variables. This can be thought of analogously to "the
stack" as it's used by native applications. Basic scalars (null, bool,
int, float) sit in this space with no additional pointers to anywhere.
Non-scalars use pointers to elsewhere in the heap to store the actual
payload. This isn't unique to PHP, as these structures have runtime
determined size and thus can't** be stack allocated.
https://nikic.github.io/2017/04/14/PHP-7-Virtual-machine.html may help if you want to learn more about what the PHP VM currently does
So what’s the difference between TMP and VAR? Not much.
The distinction was inherited from PHP 5, where TMPs were VM stack allocated,
while VARs were heap allocated. In PHP 7 all variables are stack allocated.
As such, nowadays the main difference between TMPs and VARs is that only the latter are allowed to contain REFERENCEs
(this allows us to elide DEREFs on TMPs). Furthermore VARs may hold two types of special values,
namely class entries and INDIRECT values. The latter are used to handle non-trivial assignments.
-Tyson
2021-01-03 17:43 GMT, tyson andre tysonandre775@hotmail.com:
Hi Olle,
Thanks Sara! I realize I should have been more precise: Can PHP
allocate non-reference counted memory that automatically is freed when
leaving scope, similar to what Go does with escape analysis?Article describing the Go mechanism:
https://segment.com/blog/allocation-efficiency-in-high-performance-go-services/Could you give some concrete examples of what type of code you're talking
about?
As Sara Golemon said, scalars (null, bool, int, float) are allocated on a
php call frame,
and the call frames go on a stack. That stack is separate from the C stack,
but still a stackThe call frame is "freed" when leaving scope - i.e. that part of the stack
will be reused on subsequent calls.
Sure. Consider the following trivial snippet:
class Point {
public $x;
public $y;
}
function foo() {
$p = new Point();
return $p->x + $p->y;
}
Since we know the lifetime of $p, we don't have to ref count it.
Escape analysis helps with checking lifetimes and to remove needles
ref counting (and heap allocations in compiled languages). There is a
file in php-src for this:
https://github.com/php/php-src/blob/master/ext/opcache/Optimizer/escape_analysis.c
My question was about how this functionality is used.
A single PHP call frame holds a block of storage space for (among other
things) all* local variables. This can be thought of analogously to "the
stack" as it's used by native applications. Basic scalars (null, bool,
int, float) sit in this space with no additional pointers to anywhere.
Non-scalars use pointers to elsewhere in the heap to store the actual
payload. This isn't unique to PHP, as these structures have runtime
determined size and thus can't** be stack allocated.https://nikic.github.io/2017/04/14/PHP-7-Virtual-machine.html may help if
you want to learn more about what the PHP VM currently does
Nice link, thanks!
Olle
On Mon, Jan 4, 2021 at 11:53 AM Olle Härstedt olleharstedt@gmail.com
wrote:
2021-01-03 17:43 GMT, tyson andre tysonandre775@hotmail.com:
Hi Olle,
Thanks Sara! I realize I should have been more precise: Can PHP
allocate non-reference counted memory that automatically is freed when
leaving scope, similar to what Go does with escape analysis?Article describing the Go mechanism:
https://segment.com/blog/allocation-efficiency-in-high-performance-go-services/
Could you give some concrete examples of what type of code you're talking
about?
As Sara Golemon said, scalars (null, bool, int, float) are allocated on a
php call frame,
and the call frames go on a stack. That stack is separate from the C
stack,
but still a stackThe call frame is "freed" when leaving scope - i.e. that part of the
stack
will be reused on subsequent calls.Sure. Consider the following trivial snippet:
class Point { public $x; public $y; } function foo() { $p = new Point(); return $p->x + $p->y; }
Since we know the lifetime of $p, we don't have to ref count it.
Escape analysis helps with checking lifetimes and to remove needles
ref counting (and heap allocations in compiled languages). There is a
file in php-src for this:https://github.com/php/php-src/blob/master/ext/opcache/Optimizer/escape_analysis.c
My question was about how this functionality is used.
I believe the escape analysis is currently only used as part of SCCP to
perform constant folding on objects. For example, we would be able to fold
the following function down to "return 3;":
function foo() {
$p = new Point();
$p->x = 1;
$p->y = 2;
return $p->x + $p->y;
}
However, I think the optimization you have in mind is more along the lines
of dropping the object and storing its properties as local variables
instead.
I don't think the escape analysis is particularly useful outside of
stdClass possibly, as it will bail on classes from different files, and
classes with constructors anyway.
Nikita
2021-01-05 10:51 GMT, Nikita Popov nikita.ppv@gmail.com:
On Mon, Jan 4, 2021 at 11:53 AM Olle Härstedt olleharstedt@gmail.com
wrote:2021-01-03 17:43 GMT, tyson andre tysonandre775@hotmail.com:
Hi Olle,
Thanks Sara! I realize I should have been more precise: Can PHP
allocate non-reference counted memory that automatically is freed when
leaving scope, similar to what Go does with escape analysis?Article describing the Go mechanism:
https://segment.com/blog/allocation-efficiency-in-high-performance-go-services/
Could you give some concrete examples of what type of code you're
talking
about?
As Sara Golemon said, scalars (null, bool, int, float) are allocated on
a
php call frame,
and the call frames go on a stack. That stack is separate from the C
stack,
but still a stackThe call frame is "freed" when leaving scope - i.e. that part of the
stack
will be reused on subsequent calls.Sure. Consider the following trivial snippet:
class Point { public $x; public $y; } function foo() { $p = new Point(); return $p->x + $p->y; }
Since we know the lifetime of $p, we don't have to ref count it.
Escape analysis helps with checking lifetimes and to remove needles
ref counting (and heap allocations in compiled languages). There is a
file in php-src for this:https://github.com/php/php-src/blob/master/ext/opcache/Optimizer/escape_analysis.c
My question was about how this functionality is used.
I believe the escape analysis is currently only used as part of SCCP to
perform constant folding on objects. For example, we would be able to fold
the following function down to "return 3;":function foo() {
$p = new Point();
$p->x = 1;
$p->y = 2;
return $p->x + $p->y;
}However, I think the optimization you have in mind is more along the lines
of dropping the object and storing its properties as local variables
instead.
Hm, this is called scalar replacement, I think.
Olle
On Sun, Jan 3, 2021 at 10:37 AM Olle Härstedt olleharstedt@gmail.com
wrote:
Thanks Sara! I realize I should have been more precise: Can PHP
allocate non-reference counted memory that automatically is freed when
leaving scope, similar to what Go does with escape analysis?
It seems like you're conflating userspace variables and their underlying
data storage mechanisms and while the two are related and have naturally
similar semantics, they're not really the same thing and trying to
generically talk about both at the same time is only going to add to
confusion.
If you're talking about userspace variables... Yeah. They're scope bound
and destructed/freed on scope exit. Nearly every language does some form
of this because to not do so would be leaky and awful.
If you're talking about internal memory allocators, then the idea of
"automatically freed" is a red-herring. It's an illusion created by some
languages to cover up the quite explicit mechanisms in place to handle data
lifetimes. PHP does its form of this as well using a combination of stack
and heap allocators as appropriate.
-Sara