And*_*kus 8 php c php-extension php-internals
我正在开发一个PHP扩展,其中一个对象方法需要返回一个数组zval.
该方法如下:
ZEND_METHOD(myObject, myMethod)
{
zval **myArrayProperty;
if (zend_hash_find(Z_OBJPROP_P(getThis()), "myArrayProperty", sizeof("myArrayProperty"), (void **) &myArrayProperty) == FAILURE) {
RETURN_FALSE;
}
RETURN_ZVAL(*myArrayProperty, 1, 0);
}
Run Code Online (Sandbox Code Playgroud)
代码工作正常,并做了预期的事情 - 它返回对象的myArrayProperty.但是,我想优化这个过程.
myArrayProperty存储一个可能很大的数组.并且RETURN_ZVAL()宏复制该数组以返回值.复制过程需要花费大量时间来获取内存并复制所有数组值.同时,返回的数组通常用于只读操作.所以一个很好的优化是使用PHP的机制与引用计数,不要重复myArrayProperty内容.相反我会提高refcount的myArrayProperty,只是返回指针.当使用PHP扩展中的变量时,这与通常使用的策略相同.
但是,似乎没有办法 - 你必须复制值才能从PHP扩展函数返回它.更改函数签名以通过引用返回值不是一个选项,因为它链接属性和返回值 - 即稍后更改返回值,也会更改属性.这不是一种可接受的行为.
无法参与引用计数看起来很奇怪,因为PHP中的代码相同:
function myMethod() {
{
return $this->myArrayProperty;
}
Run Code Online (Sandbox Code Playgroud)
通过引用计数机制进行优化.这就是我在StackOverflow上提出这个问题的原因,以防我错过了什么.
那么,有没有办法从PHP扩展中的函数返回一个数组,而不是在内存中复制数组?
如果你的函数返回by-value,那么只能使用RETURN_ZVAL_FAST宏从PHP 5.6(当前主数据库)开始:
RETURN_ZVAL_FAST(*myArrayProperty);
Run Code Online (Sandbox Code Playgroud)
如果函数返回by-reference(return_reference=1在arginfo中),则可以使用以下代码返回:
zval_ptr_dtor(&return_value);
SEPARATE_ZVAL_TO_MAKE_IS_REF(myArrayProperty);
Z_ADDREF_PP(myArrayProperty);
*return_value_ptr = *myArrayProperty;
Run Code Online (Sandbox Code Playgroud)
如果你的函数按值返回并且你使用的是PHP 5.5或更高版本,你仍然可以优化refcount=1大小写:
if (Z_REFCOUNT_PP(myArrayProperty) == 1) {
RETVAL_ZVAL(*myArrayProperty, 0, 1);
Z_ADDREF_P(return_value);
*myArrayProperty = return_value;
} else {
RETVAL_ZVAL(*myArrayProperty, 1, 0);
}
Run Code Online (Sandbox Code Playgroud)
Jim*_*ini -1
自从我编写了这样的代码以来已经有一段时间了\xe2\x80\xa6
\n\n所以,我在下面的代码中做了什么:1)。显式增加引用计数器 2)。返回 zval 而不复制它
\n\nZEND_METHOD(myObject, myMethod)\n{\n zval **myArrayProperty;\n\n if (zend_hash_find(Z_OBJPROP_P(getThis()), "myArrayProperty", sizeof("myArrayProperty"), (void **) &myArrayProperty) == FAILURE) {\n RETURN_FALSE;\n }\n\n Z_ADDREF_PP(myArrayProperty);\n RETURN_ZVAL(*myArrayProperty, 0, 0);\n}\nRun Code Online (Sandbox Code Playgroud)\n