Skip to content

Commit 367f303

Browse files
authored
Optimize DOM property access (php#15626)
For the read and write implementation, store the handler pointer in the first cache slot. For the write implementation, use the second cache slot to store the property info. For a micro-benchmark that performs a write: ```php $dom = new DOMDocument; for ($i=0;$i<9999999;$i++) $dom->strictErrorChecking = false; ``` I obtain the following results on an i7-4790: ``` ./sapi/cli/php ./write.php ran 1.42 ± 0.08 times faster than ./sapi/cli/php_old ./write.php ``` For a micro-benchmark that performs a read: ```php $dom = new DOMDocument; for ($i=0;$i<9999999;$i++) $dom->strictErrorChecking; ``` I obtain the following results on the same machine: ``` ./sapi/cli/php ./read.php ran 1.29 ± 0.13 times faster than ./sapi/cli/php_old ./read.php ```
1 parent 0268cb0 commit 367f303

File tree

1 file changed

+33
-12
lines changed

1 file changed

+33
-12
lines changed

ext/dom/php_dom.c

Lines changed: 33 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -365,16 +365,31 @@ static zval *dom_get_property_ptr_ptr(zend_object *object, zend_string *name, in
365365
return NULL;
366366
}
367367

368+
static zend_always_inline const dom_prop_handler *dom_get_prop_handler(const dom_object *obj, zend_string *name, void **cache_slot)
369+
{
370+
const dom_prop_handler *hnd = NULL;
371+
372+
if (obj->prop_handler != NULL) {
373+
if (cache_slot) {
374+
hnd = *cache_slot;
375+
}
376+
if (!hnd) {
377+
hnd = zend_hash_find_ptr(obj->prop_handler, name);
378+
if (cache_slot) {
379+
*cache_slot = (void *) hnd;
380+
}
381+
}
382+
}
383+
384+
return hnd;
385+
}
386+
368387
/* {{{ dom_read_property */
369388
zval *dom_read_property(zend_object *object, zend_string *name, int type, void **cache_slot, zval *rv)
370389
{
371390
dom_object *obj = php_dom_obj_from_obj(object);
372391
zval *retval;
373-
dom_prop_handler *hnd = NULL;
374-
375-
if (obj->prop_handler != NULL) {
376-
hnd = zend_hash_find_ptr(obj->prop_handler, name);
377-
}
392+
const dom_prop_handler *hnd = dom_get_prop_handler(obj, name, cache_slot);
378393

379394
if (hnd) {
380395
int ret = hnd->read_func(obj, rv);
@@ -394,19 +409,25 @@ zval *dom_read_property(zend_object *object, zend_string *name, int type, void *
394409
zval *dom_write_property(zend_object *object, zend_string *name, zval *value, void **cache_slot)
395410
{
396411
dom_object *obj = php_dom_obj_from_obj(object);
397-
dom_prop_handler *hnd = NULL;
398-
399-
if (obj->prop_handler != NULL) {
400-
hnd = zend_hash_find_ptr(obj->prop_handler, name);
401-
}
412+
const dom_prop_handler *hnd = dom_get_prop_handler(obj, name, cache_slot);
402413

403414
if (hnd) {
404-
if (!hnd->write_func) {
415+
if (UNEXPECTED(!hnd->write_func)) {
405416
zend_readonly_property_modification_error_ex(ZSTR_VAL(object->ce->name), ZSTR_VAL(name));
406417
return &EG(error_zval);
407418
}
408419

409-
zend_property_info *prop = zend_get_property_info(object->ce, name, /* silent */ true);
420+
zend_property_info *prop = NULL;
421+
if (cache_slot) {
422+
prop = *(cache_slot + 1);
423+
}
424+
if (!prop) {
425+
prop = zend_get_property_info(object->ce, name, /* silent */ true);
426+
if (cache_slot) {
427+
*(cache_slot + 1) = prop;
428+
}
429+
}
430+
410431
ZEND_ASSERT(prop && ZEND_TYPE_IS_SET(prop->type));
411432
zval tmp;
412433
ZVAL_COPY(&tmp, value);

0 commit comments

Comments
 (0)