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