I've spent the last few days pouring over the Zend engine source code. I
think I have a basic understanding on the memory management. Likely what I
say may be incorrect, so I apologize in advance.
What I'm trying to do is write an extension to persist PHP variables past
the end of the request in the SAPI to be used on the next request (different
user, same process). I'd like to do this without serialization. The reason
is certain objects in PHP (in a framework, for example) are not request
specific and it would be useful to have these objects already loaded and
usable without having to construct them on every request. (Sample use case:
Dependency injection like Guice without having to write physical containers
- using reflection, written in PHP)
From what I've gathered thus far, it is impossible to do without copying the
non-persistent memory into persistent memory, and then back again. I'm
assuming this is because all the memory associated with PHP variables use
emalloc, which places it onto a stack that is disposed of at the end of the
request.
So there seems to only be two ways to do this:
1 - Copy non-persistent memory into persistent memory (and back) using a
deep copy. Probably not very efficient. May not be much better than
serialization.
2 - Modify the Zend engine to flag objects/zvals as persistent so they
aren¹t thrown away until the process ends.
#2 seems to be the better way to go. #1 seems to be the only way to do it as
an extension (maintaining its own stack).
There seems to have been some discussion (7 years ago) of this mentioned
here under 6.9:
http://www.php.net/~derick/meeting-notes.html
I've been able to do it somewhat with string zvals, but objects are a
different story (given that a zval contains a handle index referring an
entry in a bucket). The "goal", at least with objects, is the objects
doesn't destruct until the end of the process. With copying memory it looks
like I'd probably have to copy the object into my own bucket, modify the
original in zend's bucket so the destructor isn't called (destructor_callled
= 1), and then at the start of the request copy what's in my bucket into
zend's bucket.
At this point I feel light a mad scientist. I'm hoping to gain some insight
on how this might be done properly with PHP 5.3/5.4 (or just 5.4) - even if
it involves modifying the Zend engine. Have you guys had any recent
discussions about doing this?
Luke
Hi,
From what I've gathered thus far, it is impossible to do without
copying the non-persistent memory into persistent memory, and then
back again. I'm assuming this is because all the memory associated
with PHP variables use emalloc, which places it onto a stack that is
disposed of at the end of the request.So there seems to only be two ways to do this:
1 - Copy non-persistent memory into persistent memory (and back) using
a deep copy. Probably not very efficient. May not be much better than
serialization.
Yes, see apc_store() and friends to see all the small parts needed to
copy it as properly as possible. While this still won't work for all
cases (resources, internal classes, ..) but well, this might be what
you're looking for in a ready state ;-)
2 - Modify the Zend engine to flag objects/zvals as persistent so they
aren¹t thrown away until the process ends.
Which is a major undertaking, taking copy-on-write and friends into
account. As in a case like
mark_persistent($persistent);
$persistent['some key'] = function_returning_lots_of_data();
would suddenly require to create a copy of all the data. Such things can
quickly cost more than recreating the structures more frequently ...
johannes
Neat idea. I have considered writing persistent php servers that just accept requests serially. Possibly you could write a fastcgi server in pure php. That would still delegate most of the grunt work to apache.
Sent from my iPhone
I've spent the last few days pouring over the Zend engine source code. I
think I have a basic understanding on the memory management. Likely what I
say may be incorrect, so I apologize in advance.What I'm trying to do is write an extension to persist PHP variables past
the end of the request in the SAPI to be used on the next request (different
user, same process). I'd like to do this without serialization. The reason
is certain objects in PHP (in a framework, for example) are not request
specific and it would be useful to have these objects already loaded and
usable without having to construct them on every request. (Sample use case:
Dependency injection like Guice without having to write physical containers
- using reflection, written in PHP)
From what I've gathered thus far, it is impossible to do without copying the
non-persistent memory into persistent memory, and then back again. I'm
assuming this is because all the memory associated with PHP variables use
emalloc, which places it onto a stack that is disposed of at the end of the
request.So there seems to only be two ways to do this:
1 - Copy non-persistent memory into persistent memory (and back) using a
deep copy. Probably not very efficient. May not be much better than
serialization.2 - Modify the Zend engine to flag objects/zvals as persistent so they
aren¹t thrown away until the process ends.#2 seems to be the better way to go. #1 seems to be the only way to do it as
an extension (maintaining its own stack).There seems to have been some discussion (7 years ago) of this mentioned
here under 6.9:http://www.php.net/~derick/meeting-notes.html
I've been able to do it somewhat with string zvals, but objects are a
different story (given that a zval contains a handle index referring an
entry in a bucket). The "goal", at least with objects, is the objects
doesn't destruct until the end of the process. With copying memory it looks
like I'd probably have to copy the object into my own bucket, modify the
original in zend's bucket so the destructor isn't called (destructor_callled
= 1), and then at the start of the request copy what's in my bucket into
zend's bucket.At this point I feel light a mad scientist. I'm hoping to gain some insight
on how this might be done properly with PHP 5.3/5.4 (or just 5.4) - even if
it involves modifying the Zend engine. Have you guys had any recent
discussions about doing this?Luke
Indeed phpdaemon.net appears to cover this ground, although your idea might deliver higher performance.
Sent from my iPhone
I've spent the last few days pouring over the Zend engine source code. I
think I have a basic understanding on the memory management. Likely what I
say may be incorrect, so I apologize in advance.What I'm trying to do is write an extension to persist PHP variables past
the end of the request in the SAPI to be used on the next request (different
user, same process). I'd like to do this without serialization. The reason
is certain objects in PHP (in a framework, for example) are not request
specific and it would be useful to have these objects already loaded and
usable without having to construct them on every request. (Sample use case:
Dependency injection like Guice without having to write physical containers
- using reflection, written in PHP)
From what I've gathered thus far, it is impossible to do without copying the
non-persistent memory into persistent memory, and then back again. I'm
assuming this is because all the memory associated with PHP variables use
emalloc, which places it onto a stack that is disposed of at the end of the
request.So there seems to only be two ways to do this:
1 - Copy non-persistent memory into persistent memory (and back) using a
deep copy. Probably not very efficient. May not be much better than
serialization.2 - Modify the Zend engine to flag objects/zvals as persistent so they
aren¹t thrown away until the process ends.#2 seems to be the better way to go. #1 seems to be the only way to do it as
an extension (maintaining its own stack).There seems to have been some discussion (7 years ago) of this mentioned
here under 6.9:http://www.php.net/~derick/meeting-notes.html
I've been able to do it somewhat with string zvals, but objects are a
different story (given that a zval contains a handle index referring an
entry in a bucket). The "goal", at least with objects, is the objects
doesn't destruct until the end of the process. With copying memory it looks
like I'd probably have to copy the object into my own bucket, modify the
original in zend's bucket so the destructor isn't called (destructor_callled
= 1), and then at the start of the request copy what's in my bucket into
zend's bucket.At this point I feel light a mad scientist. I'm hoping to gain some insight
on how this might be done properly with PHP 5.3/5.4 (or just 5.4) - even if
it involves modifying the Zend engine. Have you guys had any recent
discussions about doing this?Luke