Hey:
we used to use lval of zval as a handle to access resource type..
but now, we introduced a new type IS_RESOURCE, which make the
handle(id) sort of redundant .
further more, the common usage when handling resource is like:
if (zend_parse_parameters(ZEND_NUM_ARGS(), "rl", &result,
&offset) == FAILURE) {
return;
}
ZEND_FETCH_RESOURCE(mysql_result, MYSQL_RES *, result, -1, "MySQL
result", le_result);
as you can see, we use "r" to receive a IS_RESOURCE type, that
means, check the type in ZEND_FETCH_RESOURCE is overhead..
and:
ZEND_API void *zend_fetch_resource(zval *passed_id, int default_id,
const char *resource_type_name, int *found_resource_type, int
num_resource_types, ...)
we use va_args to passing resource type, that means, the rescue
type arguments can not be passed by register but by stack.. which is a
little low effiicient .
so, I'd like propose a zend_resource handling API cleanup..
-
DROP ZEND_REGISTER_RESOURCE/FETCH_RESOURCE.
-
add :
ZEND_API void *zend_fetch_resource(zend_resource *res, const
char *resource_type_name, int resource_type);
ZEND_API void *zend_fetch_resource2(zend_resource *res, const char
*resource_type_name, int *found_type, int resource_type, int
resource_type2);
ZEND_API void *zend_fetch_resource_ex(zval *res, const char
*resource_type_name, int resource_type);
ZEND_API void *zend_fetch_resource2_ex(zval *res, const char
*resource_type_name, int *found_type, int resource_type, int
resource_type2);
a underworking patch could be found at:
https://github.com/php/php-src/pull/1042
any ideas & objections?
thanks
--
Xinchen Hui
@Laruence
http://www.laruence.com/
Hey:
we used to use lval of zval as a handle to access resource type.. but now, we introduced a new type IS_RESOURCE, which make the
handle(id) sort of redundant .
further more, the common usage when handling resource is like: if (zend_parse_parameters(ZEND_NUM_ARGS(), "rl", &result,
&offset) == FAILURE) {
return;
}
ZEND_FETCH_RESOURCE(mysql_result, MYSQL_RES *, result, -1, "MySQL
result", le_result);as you can see, we use "r" to receive a IS_RESOURCE type, that
means, check the type in ZEND_FETCH_RESOURCE is overhead..
and:
ZEND_API void *zend_fetch_resource(zval *passed_id, int default_id,
const char *resource_type_name, int *found_resource_type, int
num_resource_types, ...)we use va_args to passing resource type, that means, the rescue
type arguments can not be passed by register but by stack.. which is a
little low effiicient .so, I'd like propose a zend_resource handling API cleanup..
DROP ZEND_REGISTER_RESOURCE/FETCH_RESOURCE.
add :
ZEND_API void *zend_fetch_resource(zend_resource *res, const
char *resource_type_name, int resource_type);
ZEND_API void *zend_fetch_resource2(zend_resource *res, const char
*resource_type_name, int *found_type, int resource_type, int
resource_type2);
ZEND_API void *zend_fetch_resource_ex(zval *res, const char
*resource_type_name, int resource_type);
ZEND_API void *zend_fetch_resource2_ex(zval *res, const char
*resource_type_name, int *found_type, int resource_type, int
resource_type2);a underworking patch could be found at:
https://github.com/php/php-src/pull/1042any ideas & objections?
furthermore, I'd like to discuss remove the handle in zend_resource struct..
it may breaks some usage (use resource as long/double/string)
case IS_RESOURCE: {
char buf[sizeof("Resource id #") + MAX_LENGTH_OF_LONG];
int len;
len = snprintf(buf, sizeof(buf), "Resource id #"
ZEND_LONG_FMT, (zend_long)Z_RES_HANDLE_P(op));
return zend_string_init(buf, len, 0);
}
thanks
thanks
--
Xinchen Hui
@Laruence
http://www.laruence.com/
--
Xinchen Hui
@Laruence
http://www.laruence.com/
furthermore, I'd like to discuss remove the handle in zend_resource struct..
it may breaks some usage (use resource as long/double/string
I've seen uses in the wild where file handles are used as array keys (yes, I know, ugly and wrong).
If we were to remove rsrc handle, we should formally deprecate it for at least one minor revision first.
I'm all for killing it, and I fully support improving the internal API, but the gentler we are with BC breaks, the better.
-Sara
Hey Sara:
furthermore, I'd like to discuss remove the handle in zend_resource struct..
it may breaks some usage (use resource as long/double/string
I've seen uses in the wild where file handles are used as array keys (yes, I know, ugly and wrong).
If we were to remove rsrc handle, we should formally deprecate it for at least one minor revision first.
I'm all for killing it, and I fully support improving the internal API, but the gentler we are with BC breaks, the better.
I agree, as I said, removing it is the step 2 actions
we may discuss it later..
thanks
-Sara
--
Xinchen Hui
@Laruence
http://www.laruence.com/
furthermore, I'd like to discuss remove the handle in zend_resource struct..
it may breaks some usage (use resource as long/double/string
I've seen uses in the wild where file handles are used as array keys (yes, I know, ugly and wrong).
Yes, I definitely use that a lot and cannot see why this should be wrong.
If we were to remove rsrc handle, we should formally deprecate it for at least one minor revision first.
I'm all for killing it, and I fully support improving the internal API, but the gentler we are with BC breaks, the better.
De : Xinchen Hui [mailto:laruence@php.net]
furthermore, I'd like to discuss remove the handle in zend_resource struct..it may breaks some usage (use resource as long/double/string)
case IS_RESOURCE: {
char buf[sizeof("Resource id #") + MAX_LENGTH_OF_LONG];
int len;len = snprintf(buf, sizeof(buf), "Resource id #"
ZEND_LONG_FMT, (zend_long)Z_RES_HANDLE_P(op));
return zend_string_init(buf, len, 0);
}
I don't understand how you can delete the resource if you remove the handle from the zend_resource struct. Or would you store the index elsewhere ?
Regards
François
Hey:
On Tue, Feb 3, 2015 at 12:37 AM, François Laupretre
francois@tekwire.net wrote:
De : Xinchen Hui [mailto:laruence@php.net]
furthermore, I'd like to discuss remove the handle in zend_resource struct..it may breaks some usage (use resource as long/double/string)
case IS_RESOURCE: {
char buf[sizeof("Resource id #") + MAX_LENGTH_OF_LONG];
int len;len = snprintf(buf, sizeof(buf), "Resource id #"
ZEND_LONG_FMT, (zend_long)Z_RES_HANDLE_P(op));
return zend_string_init(buf, len, 0);
}I don't understand how you can delete the resource if you remove the handle from the zend_resource struct. Or would you store the index elsewhere ?
if you use HashTable , yes, it's hard to get rid of it, but we can
hidden it from user land..
and actually, we only use integer index of regular_list for zend_resource..
if we decide to remove handle, then it maybe easy to re-implement it
as a plain c array like zend_resource[];
and when doing realloce, we allocate new segment, and link them togther. etc
thanks
Regards
François
--
Xinchen Hui
@Laruence
http://www.laruence.com/
De : Xinchen Hui [mailto:laruence@php.net]
I don't understand how you can delete the resource if you remove the
handle from the zend_resource struct. Or would you store the index
elsewhere ?if you use HashTable , yes, it's hard to get rid of it, but we can
hidden it from user land..and actually, we only use integer index of regular_list for zend_resource..
if we decide to remove handle, then it maybe easy to re-implement it
as a plain c array like zend_resource[];and when doing realloce, we allocate new segment, and link them togther.
Anyway, IMO, moving resources from HashTable to a plain C array is a good thing. Allocating segments of 20 structs, for instance, would be fine as a single segment would fit 99.9 % of the cases. This way, you could even compute a pseudo resource handle from the zend_resource address (for var_dump()
). The only additional thing you would need is a field to mark the resource as deleted/invalid. But setting ptr to NULL
and type to -1 would be probably enough.
I am interested in the subject of resources because I just implemented a resource abstraction layer in php-ext-gen (https://github.com/flaupretre/php-ext-gen). The objective being to use the same user code for PHP 5 and 7. Maybe you can have a look at the project and give me your opinion.
Regards
François
De : Xinchen Hui [mailto:laruence@php.net]
we used to use lval of zval as a handle to access resource type..but now, we introduced a new type IS_RESOURCE, which make the
handle(id) sort of redundant .
Wrong. The IS_RESOURCE type has nothing to do with PHP 7. Only zend_resource is new. And handle is not redundant.
further more, the common usage when handling resource is like: if (zend_parse_parameters(ZEND_NUM_ARGS(), "rl", &result,
&offset) == FAILURE) {
return;
}
ZEND_FETCH_RESOURCE(mysql_result, MYSQL_RES *, result, -1, "MySQL
result", le_result);as you can see, we use "r" to receive a IS_RESOURCE type, that
means, check the type in ZEND_FETCH_RESOURCE is overhead..
There's no overhead here. Zend_parse_parameters checks that received arg is IS_RESOURCE. Fetch then checks that received resource is one of the accepted resource types. Sorry to say that, but are you sure you understand the difference between zval types and resource types ?
ZEND_API void *zend_fetch_resource(zval *passed_id, int default_id,
const char *resource_type_name, int *found_resource_type, int
num_resource_types, ...)we use va_args to passing resource type, that means, the rescue
type arguments can not be passed by register but by stack.. which is a
little low effiicient .
What do you mean with 'rescue' type ?
Fetch is supposed to check for a variable number of possible resource types. It could probably be restricted to 2 possible types as, generally, it is the maximum (one for non-persistent, one for persistent). But I am not sure the overhead of passing arg on the stack justifies a change. Remember that id is searched in an array, which takes probably much more time that pushing/popping one or two arguments.
so, I'd like propose a zend_resource handling API cleanup..
DROP ZEND_REGISTER_RESOURCE/FETCH_RESOURCE.
add :
ZEND_API void *zend_fetch_resource(zend_resource *res, const
char *resource_type_name, int resource_type);
ZEND_API void *zend_fetch_resource2(zend_resource *res, const char
*resource_type_name, int *found_type, int resource_type, int
resource_type2);
ZEND_API void *zend_fetch_resource_ex(zval *res, const char
*resource_type_name, int resource_type);
ZEND_API void *zend_fetch_resource2_ex(zval *res, const char
*resource_type_name, int *found_type, int resource_type, int
resource_type2);
If you drop ZEND_REGISTER_RESOURCE, how do you register new resources ? Or do you mean you don't register them any more ? But registering them is mandatory if we want them to be freed when request ends.
furthermore, I'd like to discuss remove the handle in zend_resource struct..
it may breaks some usage (use resource as long/double/string)
case IS_RESOURCE: {
char buf[sizeof("Resource id #") + MAX_LENGTH_OF_LONG];
int len;len = snprintf(buf, sizeof(buf), "Resource id #"
ZEND_LONG_FMT, (zend_long)Z_RES_HANDLE_P(op));
return zend_string_init(buf, len, 0);
}
OK. You want to remove resource registration. But resources don't work this way (see http://devzone.zend.com/446/extension-writing-part-iii-resources/). If you remove the handle, you remove the whole zend_list API.
The zend_resource struct is not a structure you may fill with random data. Using the handle to store long/double/string is not a legitimate usage.
Regards
François
Hey:
De : Xinchen Hui [mailto:laruence@php.net]
we used to use lval of zval as a handle to access resource type..but now, we introduced a new type IS_RESOURCE, which make the
handle(id) sort of redundant .
Wrong. The IS_RESOURCE type has nothing to do with PHP 7. Only zend_resource is new. And handle is not redundant.
of course it's a typo. I meant zend_resourcefurther more, the common usage when handling resource is like: if (zend_parse_parameters(ZEND_NUM_ARGS(), "rl", &result,
&offset) == FAILURE) {
return;
}
ZEND_FETCH_RESOURCE(mysql_result, MYSQL_RES *, result, -1, "MySQL
result", le_result);as you can see, we use "r" to receive a IS_RESOURCE type, that
means, check the type in ZEND_FETCH_RESOURCE is overhead..
There's no overhead here. Zend_parse_parameters checks that received arg is IS_RESOURCE. Fetch then checks that received resource is one of the accepted resource types. Sorry to say that, but are you sure you understand the difference between zval types and resource types ?
..... do you really read the FETCH_RESOURCE?
ZEND_API void *zend_fetch_resource(zval *passed_id, int default_id,
const char *resource_type_name, int *found_resource_type, int
num_resource_types, ...)
{
int actual_resource_type;
// void *resource;
va_list resource_types;
int i;
zend_resource *res;
const char *space;
const char *class_name;
if (default_id==-1) { /* use id */
if (!passed_id) {
if (resource_type_name) {
class_name = get_active_class_name(&space);
zend_error(E_WARNING, "%s%s%s(): no %s resource
supplied", class_name, space, get_active_function_name(),
resource_type_name);
}
return NULL;
} else if (Z_TYPE_P(passed_id) != IS_RESOURCE) { // < === what are this?
if (resource_type_name) {
class_name = get_active_class_name(&space);
zend_error(E_WARNING, "%s%s%s(): supplied argument is
not a valid %s resource", class_name, space,
get_active_function_name(), resource_type_name);
}
return NULL;
}
ZEND_API void *zend_fetch_resource(zval *passed_id, int default_id,
const char *resource_type_name, int *found_resource_type, int
num_resource_types, ...)we use va_args to passing resource type, that means, the rescue
type arguments can not be passed by register but by stack.. which is a
little low effiicient .What do you mean with 'rescue' type ?
expected resource_typeFetch is supposed to check for a variable number of possible resource types. It could probably be restricted to 2 possible types as, generally, it is the maximum (one for non-persistent, one for persistent). But I am not sure the overhead of passing arg on the stack justifies a change. Remember that id is searched in an array, which takes probably much more time that pushing/popping one or two arguments.
so, I'd like propose a zend_resource handling API cleanup..
DROP ZEND_REGISTER_RESOURCE/FETCH_RESOURCE.
add :
ZEND_API void *zend_fetch_resource(zend_resource *res, const
char *resource_type_name, int resource_type);
ZEND_API void *zend_fetch_resource2(zend_resource *res, const char
*resource_type_name, int *found_type, int resource_type, int
resource_type2);
ZEND_API void *zend_fetch_resource_ex(zval *res, const char
*resource_type_name, int resource_type);
ZEND_API void *zend_fetch_resource2_ex(zval *res, const char
*resource_type_name, int *found_type, int resource_type, int
resource_type2);If you drop ZEND_REGISTER_RESOURCE, how do you register new resources ? Or do you mean you don't register them any more ? But registering them is mandatory if we want them to be freed when request ends.
furthermore, I'd like to discuss remove the handle in zend_resource struct..
it may breaks some usage (use resource as long/double/string)
case IS_RESOURCE: {
char buf[sizeof("Resource id #") + MAX_LENGTH_OF_LONG];
int len;len = snprintf(buf, sizeof(buf), "Resource id #"
ZEND_LONG_FMT, (zend_long)Z_RES_HANDLE_P(op));
return zend_string_init(buf, len, 0);
}OK. You want to remove resource registration. But resources don't work this way (see http://devzone.zend.com/446/extension-writing-part-iii-resources/). If you remove the handle, you remove the whole zend_list API.
The zend_resource struct is not a structure you may fill with random data. Using the handle to store long/double/string is not a legitimate usage.
....I think you don't understand what I am talking about. sorry
thanks
Regards
François
--
Xinchen Hui
@Laruence
http://www.laruence.com/
Hey:
Hey:
De : Xinchen Hui [mailto:laruence@php.net]
we used to use lval of zval as a handle to access resource type..but now, we introduced a new type IS_RESOURCE, which make the
handle(id) sort of redundant .
Wrong. The IS_RESOURCE type has nothing to do with PHP 7. Only zend_resource is new. And handle is not redundant.
of course it's a typo. I meant zend_resourcefurther more, the common usage when handling resource is like: if (zend_parse_parameters(ZEND_NUM_ARGS(), "rl", &result,
&offset) == FAILURE) {
return;
}
ZEND_FETCH_RESOURCE(mysql_result, MYSQL_RES *, result, -1, "MySQL
result", le_result);as you can see, we use "r" to receive a IS_RESOURCE type, that
means, check the type in ZEND_FETCH_RESOURCE is overhead..
There's no overhead here. Zend_parse_parameters checks that received arg is IS_RESOURCE. Fetch then checks that received resource is one of the accepted resource types. Sorry to say that, but are you sure you understand the difference between zval types and resource types ?
..... do you really read the FETCH_RESOURCE?ZEND_API void *zend_fetch_resource(zval *passed_id, int default_id,
const char *resource_type_name, int *found_resource_type, int
num_resource_types, ...)
{
int actual_resource_type;
// void *resource;
va_list resource_types;
int i;
zend_resource *res;
const char *space;
const char *class_name;if (default_id==-1) { /* use id */ if (!passed_id) { if (resource_type_name) { class_name = get_active_class_name(&space); zend_error(E_WARNING, "%s%s%s(): no %s resource
supplied", class_name, space, get_active_function_name(),
resource_type_name);
}
return NULL;
} else if (Z_TYPE_P(passed_id) != IS_RESOURCE) { // < === what are this?
if (resource_type_name) {
class_name = get_active_class_name(&space);
zend_error(E_WARNING, "%s%s%s(): supplied argument is
not a valid %s resource", class_name, space,
get_active_function_name(), resource_type_name);
}
return NULL;
}ZEND_API void *zend_fetch_resource(zval *passed_id, int default_id,
const char *resource_type_name, int *found_resource_type, int
num_resource_types, ...)we use va_args to passing resource type, that means, the rescue
type arguments can not be passed by register but by stack.. which is a
little low effiicient .What do you mean with 'rescue' type ?
expected resource_typeFetch is supposed to check for a variable number of possible resource types. It could probably be restricted to 2 possible types as, generally, it is the maximum (one for non-persistent, one for persistent). But I am not sure the overhead of passing arg on the stack justifies a change. Remember that id is searched in an array, which takes probably much more time that pushing/popping one or two arguments.
so, I'd like propose a zend_resource handling API cleanup..
DROP ZEND_REGISTER_RESOURCE/FETCH_RESOURCE.
add :
ZEND_API void *zend_fetch_resource(zend_resource *res, const
char *resource_type_name, int resource_type);
ZEND_API void *zend_fetch_resource2(zend_resource *res, const char
*resource_type_name, int *found_type, int resource_type, int
resource_type2);
ZEND_API void *zend_fetch_resource_ex(zval *res, const char
*resource_type_name, int resource_type);
ZEND_API void *zend_fetch_resource2_ex(zval *res, const char
*resource_type_name, int *found_type, int resource_type, int
resource_type2);If you drop ZEND_REGISTER_RESOURCE, how do you register new resources ? Or do you mean you don't register them any more ? But registering them is mandatory if we want them to be freed when request ends.
furthermore, I'd like to discuss remove the handle in zend_resource struct..
it may breaks some usage (use resource as long/double/string)
case IS_RESOURCE: {
char buf[sizeof("Resource id #") + MAX_LENGTH_OF_LONG];
int len;len = snprintf(buf, sizeof(buf), "Resource id #"
ZEND_LONG_FMT, (zend_long)Z_RES_HANDLE_P(op));
return zend_string_init(buf, len, 0);
}OK. You want to remove resource registration. But resources don't work this way (see http://devzone.zend.com/446/extension-writing-part-iii-resources/). If you remove the handle, you remove the whole zend_list API.
The zend_resource struct is not a structure you may fill with random data. Using the handle to store long/double/string is not a legitimate usage.
....I think you don't understand what I am talking about. sorry
I think I'd better to explain a bit more.
we used to use handle to lookup a resource in EG(regular_list).. and
store the "int handle" into lval of zval.
but now, we use zend_resource * , which can be directly accessed via
Z_RES_P(zval).
that's why I think the "handle" is a little redundant ..
is that clear?
thanks
thanks
Regards
François
--
Xinchen Hui
@Laruence
http://www.laruence.com/
--
Xinchen Hui
@Laruence
http://www.laruence.com/
Hi,
Hey:
On Mon, Feb 2, 2015 at 2:51 PM, François Laupretre francois@tekwire.net
wrote:De : Xinchen Hui [mailto:laruence@php.net]
we used to use lval of zval as a handle to access resource type..but now, we introduced a new type IS_RESOURCE, which make the
handle(id) sort of redundant .Wrong. The IS_RESOURCE type has nothing to do with PHP 7. Only
zend_resource is new. And handle is not redundant.
of course it's a typo. I meant zend_resourcefurther more, the common usage when handling resource is like:
if (zend_parse_parameters(ZEND_NUM_ARGS(), "rl", &result, &offset) ==
FAILURE) {
return; }
ZEND_FETCH_RESOURCE(mysql_result, MYSQL_RES *, result, -1, "MySQL
result", le_result);as you can see, we use "r" to receive a IS_RESOURCE type, that means,
check the type in ZEND_FETCH_RESOURCE is overhead..There's no overhead here. Zend_parse_parameters checks that received
arg is IS_RESOURCE. Fetch then checks that received resource is one of
the accepted resource types. Sorry to say that, but are you sure you
understand the difference between zval types and resource types ?
..... do you really read the FETCH_RESOURCE?ZEND_API void *zend_fetch_resource(zval *passed_id, int default_id,
const char *resource_type_name, int *found_resource_type, int
num_resource_types, ...) {
int actual_resource_type; // void *resource;
va_list resource_types; int i; zend_resource *res; const char *space; const
char *class_name;if (default_id==-1) { /* use id */ if (!passed_id) { if
(resource_type_name) {
class_name = get_active_class_name(&space); zend_error(E_WARNING,
"%s%s%s(): no %s resource
supplied", class_name, space, get_active_function_name(),
resource_type_name); }
return NULL; } else if (Z_TYPE_P(passed_id) != IS_RESOURCE) { // < === what
are this? if (resource_type_name) { class_name =
get_active_class_name(&space); zend_error(E_WARNING, "%s%s%s(): supplied
argument is not a valid %s resource", class_name, space,
get_active_function_name(), resource_type_name); }
return NULL; }ZEND_API void *zend_fetch_resource(zval *passed_id, int default_id,
const char *resource_type_name, int *found_resource_type, int
num_resource_types, ...)we use va_args to passing resource type, that means, the rescue type
arguments can not be passed by register but by stack.. which is a
little low effiicient .What do you mean with 'rescue' type ?
expected resource_type
Fetch is supposed to check for a variable number of possible resource
types. It could probably be restricted to 2 possible types as,
generally, it is the maximum (one for non-persistent, one for
persistent). But I am not sure the overhead of passing arg on the stack
justifies a change. Remember that id is searched in an array, which
takes probably much more time that pushing/popping one or two
arguments.so, I'd like propose a zend_resource handling API cleanup..
- DROP ZEND_REGISTER_RESOURCE/FETCH_RESOURCE.
- add :
ZEND_API void *zend_fetch_resource(zend_resource *res, const
char *resource_type_name, int resource_type); ZEND_API void
*zend_fetch_resource2(zend_resource *res, const char
*resource_type_name, int *found_type, int resource_type, int
resource_type2); ZEND_API void *zend_fetch_resource_ex(zval *res, const
char *resource_type_name, int resource_type);
ZEND_API void *zend_fetch_resource2_ex(zval *res, const char
*resource_type_name, int *found_type, int resource_type, int
resource_type2);If you drop ZEND_REGISTER_RESOURCE, how do you register new resources ?
Or do you mean you don't register them any more ? But registering them
is mandatory if we want them to be freed when request ends.furthermore, I'd like to discuss remove the handle in zend_resource
struct..it may breaks some usage (use resource as long/double/string)
case IS_RESOURCE: { char buf[sizeof("Resource id #") +
MAX_LENGTH_OF_LONG];
int len;len = snprintf(buf, sizeof(buf), "Resource id #" ZEND_LONG_FMT,
(zend_long)Z_RES_HANDLE_P(op));
return zend_string_init(buf, len, 0); }OK. You want to remove resource registration. But resources don't work
this way (see
http://devzone.zend.com/446/extension-writing-part-iii-resources/). If
you remove the handle, you remove the whole zend_list API.The zend_resource struct is not a structure you may fill with random
data. Using the handle to store long/double/string is not a legitimate
usage.
....I think you don't understand what I am talking about. sorry
I was writing about it last year as well
http://marc.info/?l=php-internals&m=142006455308305&w=2 , slightly
different idea. Annd there is also a short piece of code to illustrate:
https://gist.github.com/weltling/9367db5e242ef7e60042 ...
The integer resource looks like is needed at some places, so my suggestion
was to split zend_fetch_resource function like illustrated in the patch.
At 99% of places that integer link is just passed as -1, so then having it
be present always in the signature is just a waste of "resources" :)
Regards
Anatol
Hey:
Hi,
Hey:
On Mon, Feb 2, 2015 at 2:51 PM, François Laupretre francois@tekwire.net
wrote:De : Xinchen Hui [mailto:laruence@php.net]
we used to use lval of zval as a handle to access resource type..but now, we introduced a new type IS_RESOURCE, which make the
handle(id) sort of redundant .Wrong. The IS_RESOURCE type has nothing to do with PHP 7. Only
zend_resource is new. And handle is not redundant.
of course it's a typo. I meant zend_resourcefurther more, the common usage when handling resource is like:
if (zend_parse_parameters(ZEND_NUM_ARGS(), "rl", &result, &offset) ==
FAILURE) {
return; }
ZEND_FETCH_RESOURCE(mysql_result, MYSQL_RES *, result, -1, "MySQL
result", le_result);as you can see, we use "r" to receive a IS_RESOURCE type, that means,
check the type in ZEND_FETCH_RESOURCE is overhead..There's no overhead here. Zend_parse_parameters checks that received
arg is IS_RESOURCE. Fetch then checks that received resource is one of
the accepted resource types. Sorry to say that, but are you sure you
understand the difference between zval types and resource types ?
..... do you really read the FETCH_RESOURCE?ZEND_API void *zend_fetch_resource(zval *passed_id, int default_id,
const char *resource_type_name, int *found_resource_type, int
num_resource_types, ...) {
int actual_resource_type; // void *resource;
va_list resource_types; int i; zend_resource *res; const char *space; const
char *class_name;if (default_id==-1) { /* use id */ if (!passed_id) { if
(resource_type_name) {
class_name = get_active_class_name(&space); zend_error(E_WARNING,
"%s%s%s(): no %s resource
supplied", class_name, space, get_active_function_name(),
resource_type_name); }
return NULL; } else if (Z_TYPE_P(passed_id) != IS_RESOURCE) { // < === what
are this? if (resource_type_name) { class_name =
get_active_class_name(&space); zend_error(E_WARNING, "%s%s%s(): supplied
argument is not a valid %s resource", class_name, space,
get_active_function_name(), resource_type_name); }
return NULL; }ZEND_API void *zend_fetch_resource(zval *passed_id, int default_id,
const char *resource_type_name, int *found_resource_type, int
num_resource_types, ...)we use va_args to passing resource type, that means, the rescue type
arguments can not be passed by register but by stack.. which is a
little low effiicient .What do you mean with 'rescue' type ?
expected resource_type
Fetch is supposed to check for a variable number of possible resource
types. It could probably be restricted to 2 possible types as,
generally, it is the maximum (one for non-persistent, one for
persistent). But I am not sure the overhead of passing arg on the stack
justifies a change. Remember that id is searched in an array, which
takes probably much more time that pushing/popping one or two
arguments.so, I'd like propose a zend_resource handling API cleanup..
- DROP ZEND_REGISTER_RESOURCE/FETCH_RESOURCE.
- add :
ZEND_API void *zend_fetch_resource(zend_resource *res, const
char *resource_type_name, int resource_type); ZEND_API void
*zend_fetch_resource2(zend_resource *res, const char
*resource_type_name, int *found_type, int resource_type, int
resource_type2); ZEND_API void *zend_fetch_resource_ex(zval *res, const
char *resource_type_name, int resource_type);
ZEND_API void *zend_fetch_resource2_ex(zval *res, const char
*resource_type_name, int *found_type, int resource_type, int
resource_type2);If you drop ZEND_REGISTER_RESOURCE, how do you register new resources ?
Or do you mean you don't register them any more ? But registering them
is mandatory if we want them to be freed when request ends.furthermore, I'd like to discuss remove the handle in zend_resource
struct..it may breaks some usage (use resource as long/double/string)
case IS_RESOURCE: { char buf[sizeof("Resource id #") +
MAX_LENGTH_OF_LONG];
int len;len = snprintf(buf, sizeof(buf), "Resource id #" ZEND_LONG_FMT,
(zend_long)Z_RES_HANDLE_P(op));
return zend_string_init(buf, len, 0); }OK. You want to remove resource registration. But resources don't work
this way (see
http://devzone.zend.com/446/extension-writing-part-iii-resources/). If
you remove the handle, you remove the whole zend_list API.The zend_resource struct is not a structure you may fill with random
data. Using the handle to store long/double/string is not a legitimate
usage.
....I think you don't understand what I am talking about. sorryI was writing about it last year as well
http://marc.info/?l=php-internals&m=142006455308305&w=2 , slightly
different idea. Annd there is also a short piece of code to illustrate:
https://gist.github.com/weltling/9367db5e242ef7e60042 ...The integer resource looks like is needed at some places, so my suggestion
was to split zend_fetch_resource function like illustrated in the patch.
At 99% of places that integer link is just passed as -1, so then having it
be present always in the signature is just a waste of "resources" :)
for now, we still keep the handle which could be accessed by Z_RES_HANDLE_P
I just talked about remove it later maybe.
thanks
Regards
Anatol
--
Xinchen Hui
@Laruence
http://www.laruence.com/
Hi Hui,
Hey:
On Mon, Feb 2, 2015 at 3:35 PM, Anatol Belski anatol.php@belski.net
wrote:Hi,
Hey:
On Mon, Feb 2, 2015 at 2:51 PM, François Laupretre
francois@tekwire.net
wrote:De : Xinchen Hui [mailto:laruence@php.net]
we used to use lval of zval as a handle to access resource type..but now, we introduced a new type IS_RESOURCE, which make the
handle(id) sort of redundant .Wrong. The IS_RESOURCE type has nothing to do with PHP 7. Only
zend_resource is new. And handle is not redundant.
of course it's a typo. I meant zend_resourcefurther more, the common usage when handling resource is like:
if (zend_parse_parameters(ZEND_NUM_ARGS(), "rl", &result,
&offset) ==
FAILURE) {
return; } ZEND_FETCH_RESOURCE(mysql_result, MYSQL_RES *, result,
-1, "MySQL
result", le_result);as you can see, we use "r" to receive a IS_RESOURCE type, that
means, check the type in ZEND_FETCH_RESOURCE is overhead..There's no overhead here. Zend_parse_parameters checks that
received arg is IS_RESOURCE. Fetch then checks that received
resource is one of the accepted resource types. Sorry to say that,
but are you sure you understand the difference between zval types
and resource types ?
..... do you really read the FETCH_RESOURCE?ZEND_API void *zend_fetch_resource(zval *passed_id, int default_id,
const char *resource_type_name, int *found_resource_type, int
num_resource_types, ...) { int actual_resource_type; // void
*resource;
va_list resource_types; int i; zend_resource *res; const char *space;
const char *class_name;if (default_id==-1) { /* use id */ if (!passed_id) { if
(resource_type_name) {
class_name = get_active_class_name(&space); zend_error(E_WARNING,
"%s%s%s(): no %s resource
supplied", class_name, space, get_active_function_name(),
resource_type_name); } return NULL; } else if (Z_TYPE_P(passed_id) !=
IS_RESOURCE) { // < ===
what are this? if (resource_type_name) { class_name =
get_active_class_name(&space); zend_error(E_WARNING, "%s%s%s():
supplied argument is not a valid %s resource", class_name, space,
get_active_function_name(), resource_type_name); } return NULL; }ZEND_API void *zend_fetch_resource(zval *passed_id, int
default_id, const char *resource_type_name, int
*found_resource_type, int
num_resource_types, ...)we use va_args to passing resource type, that means, the rescue
type arguments can not be passed by register but by stack.. which
is a little low effiicient .What do you mean with 'rescue' type ?
expected resource_type
Fetch is supposed to check for a variable number of possible
resource types. It could probably be restricted to 2 possible types
as, generally, it is the maximum (one for non-persistent, one for
persistent). But I am not sure the overhead of passing arg on the
stack justifies a change. Remember that id is searched in an array,
which takes probably much more time that pushing/popping one or two
arguments.so, I'd like propose a zend_resource handling API cleanup..
- DROP ZEND_REGISTER_RESOURCE/FETCH_RESOURCE.
- add :
ZEND_API void *zend_fetch_resource(zend_resource *res, const
char *resource_type_name, int resource_type); ZEND_API void
*zend_fetch_resource2(zend_resource *res, const char
*resource_type_name, int *found_type, int resource_type, int
resource_type2); ZEND_API void *zend_fetch_resource_ex(zval *res,
const char *resource_type_name, int resource_type); ZEND_API void
*zend_fetch_resource2_ex(zval *res, const char
*resource_type_name, int *found_type, int resource_type, int
resource_type2);If you drop ZEND_REGISTER_RESOURCE, how do you register new
resources ? Or do you mean you don't register them any more ? But
registering them is mandatory if we want them to be freed when
request ends.furthermore, I'd like to discuss remove the handle in
zend_resource struct..it may breaks some usage (use resource as long/double/string)
case IS_RESOURCE: { char buf[sizeof("Resource id #") +
MAX_LENGTH_OF_LONG];
int len;len = snprintf(buf, sizeof(buf), "Resource id #" ZEND_LONG_FMT,
(zend_long)Z_RES_HANDLE_P(op));
return zend_string_init(buf, len, 0); }OK. You want to remove resource registration. But resources don't
work this way (see
http://devzone.zend.com/446/extension-writing-part-iii-resources/).
If
you remove the handle, you remove the whole zend_list API.The zend_resource struct is not a structure you may fill with
random data. Using the handle to store long/double/string is not a
legitimate usage.
....I think you don't understand what I am talking about. sorryI was writing about it last year as well
http://marc.info/?l=php-internals&m=142006455308305&w=2 , slightly
different idea. Annd there is also a short piece of code to illustrate:
https://gist.github.com/weltling/9367db5e242ef7e60042 ...The integer resource looks like is needed at some places, so my
suggestion was to split zend_fetch_resource function like illustrated in
the patch. At 99% of places that integer link is just passed as -1, so
then having it be present always in the signature is just a waste of
"resources" :)for now, we still keep the handle which could be accessed by
Z_RES_HANDLE_PI just talked about remove it later maybe.
yeah, I see, u suggest even more so that int thing to be removed from the
struct. But probably one could go this way then - first cleanup the
signature, stabilize. That would give us the ground to localize the
->handle use cases and remove it in the next step. Kind of step by step
doing.
Regards
Anatol
De : Xinchen Hui [mailto:laruence@php.net]
we used to use lval of zval as a handle to access resource type..but now, we introduced a new type IS_RESOURCE, which make the
handle(id) sort of redundant .Wrong. The IS_RESOURCE type has nothing to do with PHP 7. Only zend_resource is new. And handle is not redundant.
further more, the common usage when handling resource is like:
if (zend_parse_parameters(ZEND_NUM_ARGS(), "rl", &result,
&offset) == FAILURE) {
return;
}
ZEND_FETCH_RESOURCE(mysql_result, MYSQL_RES *, result, -1, "MySQL
result", le_result);as you can see, we use "r" to receive a IS_RESOURCE type, that
means, check the type in ZEND_FETCH_RESOURCE is overhead..There's no overhead here. Zend_parse_parameters checks that received arg is IS_RESOURCE. Fetch then checks that received resource is one of the accepted resource types. Sorry to say that, but are you sure you understand the difference between zval types and resource types ?
Are you kidding? he is one of the main authors of PHP7..ZEND_API void *zend_fetch_resource(zval *passed_id, int default_id,
const char *resource_type_name, int *found_resource_type, int
num_resource_types, ...)we use va_args to passing resource type, that means, the rescue
type arguments can not be passed by register but by stack.. which is a
little low effiicient .What do you mean with 'rescue' type ?
Fetch is supposed to check for a variable number of possible resource types. It could probably be restricted to 2 possible types as, generally, it is the maximum (one for non-persistent, one for persistent). But I am not sure the overhead of passing arg on the stack justifies a change. Remember that id is searched in an array, which takes probably much more time that pushing/popping one or two arguments.
so, I'd like propose a zend_resource handling API cleanup..
DROP ZEND_REGISTER_RESOURCE/FETCH_RESOURCE.
add :
ZEND_API void *zend_fetch_resource(zend_resource *res, const
char *resource_type_name, int resource_type);
ZEND_API void *zend_fetch_resource2(zend_resource *res, const char
*resource_type_name, int *found_type, int resource_type, int
resource_type2);
ZEND_API void *zend_fetch_resource_ex(zval *res, const char
*resource_type_name, int resource_type);
ZEND_API void *zend_fetch_resource2_ex(zval *res, const char
*resource_type_name, int *found_type, int resource_type, int
resource_type2);If you drop ZEND_REGISTER_RESOURCE, how do you register new resources ? Or do you mean you don't register them any more ? But registering them is mandatory if we want them to be freed when request ends.
furthermore, I'd like to discuss remove the handle in zend_resource struct..
it may breaks some usage (use resource as long/double/string)
case IS_RESOURCE: {
char buf[sizeof("Resource id #") + MAX_LENGTH_OF_LONG];
int len;len = snprintf(buf, sizeof(buf), "Resource id #"
ZEND_LONG_FMT, (zend_long)Z_RES_HANDLE_P(op));
return zend_string_init(buf, len, 0);
}OK. You want to remove resource registration. But resources don't work this way (see http://devzone.zend.com/446/extension-writing-part-iii-resources/). If you remove the handle, you remove the whole zend_list API.
The zend_resource struct is not a structure you may fill with random data. Using the handle to store long/double/string is not a legitimate usage.
Regards
François
--
Best,
Wei Dai
Sorry to say that, but are you sure you understand the difference between zval types and resource types ?
Thanks, you made my day.
Hey:
if no objections, I will commit it.. (no bc breaks, no handle
removing , only APIs change)
dmitry suggest we change zend_fetch_resource to
zend_verify_resource, I think it make sense.. will do it.
thanks
Hey:
we used to use lval of zval as a handle to access resource type.. but now, we introduced a new type IS_RESOURCE, which make the
handle(id) sort of redundant .
further more, the common usage when handling resource is like: if (zend_parse_parameters(ZEND_NUM_ARGS(), "rl", &result,
&offset) == FAILURE) {
return;
}
ZEND_FETCH_RESOURCE(mysql_result, MYSQL_RES *, result, -1, "MySQL
result", le_result);as you can see, we use "r" to receive a IS_RESOURCE type, that
means, check the type in ZEND_FETCH_RESOURCE is overhead..
and:
ZEND_API void *zend_fetch_resource(zval *passed_id, int default_id,
const char *resource_type_name, int *found_resource_type, int
num_resource_types, ...)we use va_args to passing resource type, that means, the rescue
type arguments can not be passed by register but by stack.. which is a
little low effiicient .so, I'd like propose a zend_resource handling API cleanup..
DROP ZEND_REGISTER_RESOURCE/FETCH_RESOURCE.
add :
ZEND_API void *zend_fetch_resource(zend_resource *res, const
char *resource_type_name, int resource_type);
ZEND_API void *zend_fetch_resource2(zend_resource *res, const char
*resource_type_name, int *found_type, int resource_type, int
resource_type2);
ZEND_API void *zend_fetch_resource_ex(zval *res, const char
*resource_type_name, int resource_type);
ZEND_API void *zend_fetch_resource2_ex(zval *res, const char
*resource_type_name, int *found_type, int resource_type, int
resource_type2);a underworking patch could be found at:
https://github.com/php/php-src/pull/1042any ideas & objections?
thanks
--
Xinchen Hui
@Laruence
http://www.laruence.com/
--
Xinchen Hui
@Laruence
http://www.laruence.com/
Hey:
Hey:
we used to use lval of zval as a handle to access resource type.. but now, we introduced a new type IS_RESOURCE, which make the
handle(id) sort of redundant .
further more, the common usage when handling resource is like: if (zend_parse_parameters(ZEND_NUM_ARGS(), "rl", &result,
&offset) == FAILURE) {
return;
}
ZEND_FETCH_RESOURCE(mysql_result, MYSQL_RES *, result, -1, "MySQL
result", le_result);as you can see, we use "r" to receive a IS_RESOURCE type, that
means, check the type in ZEND_FETCH_RESOURCE is overhead..
and:
ZEND_API void *zend_fetch_resource(zval *passed_id, int default_id,
const char *resource_type_name, int *found_resource_type, int
num_resource_types, ...)we use va_args to passing resource type, that means, the rescue
type arguments can not be passed by register but by stack.. which is a
little low effiicient .so, I'd like propose a zend_resource handling API cleanup..
DROP ZEND_REGISTER_RESOURCE/FETCH_RESOURCE.
add :
ZEND_API void *zend_fetch_resource(zend_resource *res, const
char *resource_type_name, int resource_type);
ZEND_API void *zend_fetch_resource2(zend_resource *res, const char
*resource_type_name, int *found_type, int resource_type, int
resource_type2);
ZEND_API void *zend_fetch_resource_ex(zval *res, const char
*resource_type_name, int resource_type);
ZEND_API void *zend_fetch_resource2_ex(zval *res, const char
*resource_type_name, int *found_type, int resource_type, int
resource_type2);a underworking patch could be found at:
https://github.com/php/php-src/pull/1042any ideas & objections?
thanks
merged, all tests passes.
thanks
--
Xinchen Hui
@Laruence
http://www.laruence.com/
--
Xinchen Hui
@Laruence
http://www.laruence.com/
Hi!
as you can see, we use "r" to receive a IS_RESOURCE type, that
means, check the type in ZEND_FETCH_RESOURCE is overhead..
Except that some functions could receive "z" and decide if it's the
resource or not afterwards... But I guess you could rely on the code
that decides it to check. Some code would crash (or produce some very
bad memory corruption) if somebody would forget to add this check when
porting such extension. Is saving one branch worth it?
ZEND_API void *zend_fetch_resource(zval *passed_id, int default_id,
const char *resource_type_name, int *found_resource_type, int
num_resource_types, ...)we use va_args to passing resource type, that means, the rescue
type arguments can not be passed by register but by stack.. which is a
little low effiicient .
Is it that bad? Functions are passing arguments via the stack all
around. The interface with fetch(), fetch2(), fetch3(), fetch4(), etc.
looks a little clunky.
As for storing the value directly instead of having the list - it would
work for all cases except for two important ones:
- Persistent resources - they need to be stored somewhere, and not in
zvals that are supposed to be dead at the end of the request. - Cleanup at the end for non-persistent ones - zvals may be lost and
not destructed in many exceptional situations. Not destructing the
resource may mean having a stale lock forever or consuming connections
or handles, etc. So there should be some mechanism allowing for
destroying all resources that are transient.
--
Stas Malyshev
smalyshev@gmail.com