Stanislav Malyshev wrote:
>
> opcodes can be cached (bytecode caches do it) but op_array can't
> really be cached between requests because it contains dynamic
> structures. Unlike Java, PHP does full cleanup after each request,
> which means no preserving dynamic data.

APC deep-copies the whole zend_op_array, see apc_copy_op_array() in
apc_compile.c. It does it using an impressive pile of hacks which break
with every major release and in some minor releases too. Every time the
compiler allocates memory, there has to be a matching shared memory
allocation in APC.

But maybe you missed my point. I'm talking about a cache which is cheap
to construct and cleared at the end of each request. It would optimise
tight loops of calls to user-defined functions. The dynamic data, like
static variable hashtables, would be in it. The compact pointerless
structure could be stored between requests, and would not contain
dynamic data.

Basically a structure like the current zend_op_array would be created on
demand by the executor instead of in advance by the compiler.

>
> I'm not sure how using pointers in op_array in such manner would help
> though - you'd still need to store things like function names, for
> example, and since you need to store it somewhere, you'd also have
> some pointer to this place.

You can do it with a length field and a char[1] at the end of the
structure. When you allocate memory for the structure, you add some on
for the string. Then you copy the string into the char[1], overflowing it.

If you need several strings, then you can have several byte offsets,
which are added to the start of the char[1] to find the location of the
string in question. You can make the offset fields small, say 16 bits.

But it's mostly zend_op I'm interested in rather than zend_op_array.
Currently if a zend_op has a string literal argument, you'd make a zval
for it and copy it into op1.u.constant. But the zval allocation could be
avoided. The handler could cast the zend_op to a zend_op_with_a_string,
which would have a length field and an overflowed char[1] at the end for
the string argument.

A variable op size would make iterating through zend_op_array.opcodes
would be slightly more awkward, something like:

for (; op < oparray_end; op = (zend_op*)((char*)op + op->size)) {
   ...

But obviously you could clean that up with a macro.

For Mr. "everyone has 8GB of memory and tiny little data sets" Lerdorf,
I could point out that reducing the average zend_op size and placing
strings close to other op data will also make execution faster, due to
the improved CPU cache hit rate.

-- Tim Starling

-- 
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php

Reply via email to