Re: com php-src: Optimize zend_mm_small_size_to_bin() It removes a cmov operation and has a much faster branch for small allocations (especially when
handling strings) (<= 64 bytes): Zend/zend_alloc.c Zend/zend_closures.c Zend/zend_execute.c
| From: | Dmitry Stogov | Date: | Tue, 22 Sep 2015 09:47:54 +0000 |
| Subject: | Re: com php-src: Optimize zend_mm_small_size_to_bin() It removes a cmov operation and has a much faster branch for small allocations (especially when handling strings) (<= 64 bytes): Zend/zend_alloc.c Zend/zend_closures.c Zend/zend_execute.c |
||
| References: | 1 | Groups: | php.cvs |
| Request: | Send a blank email to php-cvs+get-89107@lists.php.net to get a copy of this message | ||
Hi Bob,
that code was carefully designed to avoid branch miss-predictions.
You saved few instructions but introduced branch instruction that often may
take both paths.
This mean, we may get branch miss-predictions, I-Cache misses, etc.
Finally this may lead to slower execution.
Did you measure the difference?
Checks for op_array->cache_size was also omitted on purpose (to avoid extra
checks).
I'm tired to ask you showing your patches before commit. :(
Thanks. Dmitry.
On Sun, Sep 20, 2015 at 12:07 AM, Bob Weinand <bwoebi@php.net> wrote:
> Commit: 08e253cdbc0a98e160cfd9c810ba213c7bcb3512
> Author: Bob Weinand <bobwei9@hotmail.com> Sat, 19 Sep 2015
> 23:07:43 +0200
> Parents: b8f56013b5501071a0fa5c74401afe861e5519f7
> Branches: PHP-7.0
>
> Link:
>
> http://git.php.net/?p=php-src.git;a=commitdiff;h=08e253cdbc0a98e160cfd9c810ba213c7bcb3512
>
> Log:
> Optimize zend_mm_small_size_to_bin()
> It removes a cmov operation and has a much faster branch for small
> allocations (especially when handling strings) (<= 64 bytes)
>
> Changed paths:
> M Zend/zend_alloc.c
> M Zend/zend_closures.c
> M Zend/zend_execute.c
>
>
> Diff:
> diff --git a/Zend/zend_alloc.c b/Zend/zend_alloc.c
> index bf147f5..bd3fe0e 100644
> --- a/Zend/zend_alloc.c
> +++ b/Zend/zend_alloc.c
> @@ -1202,17 +1202,19 @@ static zend_always_inline int
> zend_mm_small_size_to_bin(size_t size)
> n = zend_mm_small_size_to_bit(size - 1);
> return ((size-1) >> f1[n]) + f2[n];
> #else
> - int t1, t2, t3;
> -
> - if (UNEXPECTED(size <= 8)) return 0;
> - t1 = (int)(size - 1);
> - t2 = zend_mm_small_size_to_bit(t1);
> - t3 = t2 - 6;
> - t3 = (t3 < 0) ? 0 : t3;
> - t2 = t3 + 3;
> - t1 = t1 >> t2;
> - t3 = t3 << 2;
> - return t1 + t3;
> + unsigned int t1, t2;
> +
> + if (size <= 64) {
> + /* we need to support size == 0 ... */
> + return (size - !!size) >> 3;
> + } else {
> + t1 = size - 1;
> + t2 = zend_mm_small_size_to_bit(t1) - 3;
> + t1 = t1 >> t2;
> + t2 = t2 - 3;
> + t2 = t2 << 2;
> + return (int)(t1 + t2);
> + }
> #endif
> }
>
> diff --git a/Zend/zend_closures.c b/Zend/zend_closures.c
> index 50aa7d4..251710e 100644
> --- a/Zend/zend_closures.c
> +++ b/Zend/zend_closures.c
> @@ -134,7 +134,7 @@ ZEND_METHOD(Closure, call)
> fci_cache.function_handler = &my_function;
>
> /* Runtime cache relies on bound scope to be immutable,
> hence we need a separate rt cache in case scope changed */
> - if (ZEND_USER_CODE(my_function.type) &&
> closure->func.common.scope != Z_OBJCE_P(newthis)) {
> + if (ZEND_USER_CODE(my_function.type) &&
> closure->func.common.scope != Z_OBJCE_P(newthis) &&
> my_function.op_array.cache_size) {
> my_function.op_array.run_time_cache =
> emalloc(my_function.op_array.cache_size);
> memset(my_function.op_array.run_time_cache, 0,
> my_function.op_array.cache_size);
> }
> @@ -206,7 +206,7 @@ ZEND_METHOD(Closure, bind)
> new_closure = (zend_closure *) Z_OBJ_P(return_value);
>
> /* Runtime cache relies on bound scope to be immutable, hence we
> need a separate rt cache in case scope changed */
> - if (ZEND_USER_CODE(closure->func.type) &&
> (closure->func.common.scope != new_closure->func.common.scope ||
> (closure->func.op_array.fn_flags & ZEND_ACC_NO_RT_ARENA))) {
> + if (ZEND_USER_CODE(closure->func.type) &&
> (closure->func.common.scope != new_closure->func.common.scope ||
> (closure->func.op_array.fn_flags & ZEND_ACC_NO_RT_ARENA)) &&
> new_closure->func.op_array.cache_size) {
> new_closure->func.op_array.run_time_cache =
> emalloc(new_closure->func.op_array.cache_size);
> memset(new_closure->func.op_array.run_time_cache, 0,
> new_closure->func.op_array.cache_size);
>
> @@ -543,7 +543,7 @@ ZEND_API void zend_create_closure(zval *res,
> zend_function *func, zend_class_ent
>
> zend_hash_init(closure->func.op_array.static_variables,
> zend_hash_num_elements(static_variables), NULL, ZVAL_PTR_DTOR, 0);
> zend_hash_apply_with_arguments(static_variables,
> zval_copy_static_var, 1, closure->func.op_array.static_variables);
> }
> - if (UNEXPECTED(!closure->func.op_array.run_time_cache)) {
> + if (UNEXPECTED(!closure->func.op_array.run_time_cache) &&
> func->op_array.cache_size) {
> closure->func.op_array.run_time_cache =
> func->op_array.run_time_cache = zend_arena_alloc(&CG(arena),
> func->op_array.cache_size);
> memset(func->op_array.run_time_cache, 0,
> func->op_array.cache_size);
> }
> diff --git a/Zend/zend_execute.c b/Zend/zend_execute.c
> index 67a6bc2..dcf2d4a 100644
> --- a/Zend/zend_execute.c
> +++ b/Zend/zend_execute.c
> @@ -2166,7 +2166,7 @@ static zend_always_inline void
> i_init_func_execute_data(zend_execute_data *execu
> GC_REFCOUNT(Z_OBJ(EX(This)))++;
> }
>
> - if (UNEXPECTED(!op_array->run_time_cache)) {
> + if (UNEXPECTED(!op_array->run_time_cache) && op_array->cache_size)
> {
> op_array->run_time_cache = zend_arena_alloc(&CG(arena),
> op_array->cache_size);
> memset(op_array->run_time_cache, 0, op_array->cache_size);
> }
> @@ -2193,7 +2193,7 @@ static zend_always_inline void
> i_init_code_execute_data(zend_execute_data *execu
> GC_REFCOUNT(Z_OBJ(EX(This)))++;
> }
>
> - if (!op_array->run_time_cache) {
> + if (!op_array->run_time_cache && op_array->cache_size) {
> op_array->run_time_cache = emalloc(op_array->cache_size);
> memset(op_array->run_time_cache, 0, op_array->cache_size);
> }
>
>
> --
> PHP CVS Mailing List (http://www.php.net/)
> To unsubscribe, visit: http://www.php.net/unsub.php
>
>