Make ZVAL persistent across the SAPI?

Go To


A ZVAL is typically created with emalloc so it is destroyed at the end of a page request. Is there a way to take an existing ZVAL and make it persist in the SAPI (equivalent of pemalloc)? What about creating a ZVAL with pemalloc?

Ideally what I'd like to do (in PHP code) is this:

class Object
    public $foo;

if(!($object = persist("object")))
   $object = persist("object", new Object());

$object->foo[] = "bar";

print count($object->foo);

On each request count would return +1 (assuming the same PHP "worker" is used every time - I'm using PHP-FPM).

2012-04-03 22:28
by Luke
Nice question. + - Flavius 2012-04-04 08:09
As an interesting note: We've decided to change platforms. We'll now be using Go - Luke 2012-09-15 21:03
Cool. Could you elaborate on the reasons? I'm looking at go myself, it would be nice to know other people's motivations - Flavius 2012-09-16 05:09
We needed an active application instance. We also needed parallel execution. We evaluated Node and Java as well. Node is single threaded and uses an async model. Java uses a traditional threading model (difficult). Go makes parallel execution extremely easy, and has some other nice features. Best of all Go is compiled, but has the flexibility of a scripting language. It's getting a lot of traction. It is new, but we figured that it's at least faster than PHP :) - Luke 2012-09-16 05:24


You're basically describing

The closest you can get without duplicating functionality which is already in shm is The catch: in a prefork/multiprocess SAPI (like apache's), different requests from the same client may end up in different processes, and as such, you'll see different data (try it on Linux + Firefox with a hard refresh every time in the browser).

Note: It's a work-in-progress, currently it persists only an integer. Adding an array should be trivial. Patches welcome. It still needs the deserialization part, and to actually use persist()'s first parameter.

2012-04-04 03:02
by Flavius
That's actually ok. It doesn't need to persist across different processes/threads. The goal is to have certain objects be pre-loaded so they don't have to be initialized every time - Luke 2012-04-04 07:50
What if I were to keep a reference to the parent zval and flagged it as permanent or copied it before the request shutdown. That should work, I'm just not sure how to make an existing zval permanent. I know I can create a new permanent zval with the ALLOCPERMANENTZVAL macro - Luke 2012-04-04 15:30
What is "the parent zval"? Anyway it wouldn't work, because the zval may have disappeared in the meanwhile, or worse: it may have got replaced by another zval (so you may end up with another value in your zval if you are lucky, if not, you'll get a segfault) - Flavius 2012-04-04 15:43
In my example it's "$object". Basically I'm thinking I can increment the reference count by 1 and keep track of the zval in a hash table. Then in the request shutdown extension make the zval persist by either marking it and it's children as persistent or by making a deep copy with permalloc. If someone overwrites $object or it goes out of scope that should be ok - the incremented refcount should keep it from being gc'd. It only keeps track of the zval placed in the persist() function. The variable $object is irrelevant after that. Changes to the scale children should be captured though - Luke 2012-04-04 15:51
@Luke I've implemented your idea, the deserialization part still has to be done. It works with a single zval* only. If you're interested, feel free to send pull requests. Good luck - Flavius 2012-04-05 12:57
Seems like the only way is to serialize. There may be other options for pre-loading framework classes. See discussion on internals mailing list: - Luke 2012-04-09 23:13


zend_object can't be persisent therefore you can't do this. extensions like APC serializes the object into memory.

2015-09-05 07:49
by c9s