[njs] Optimizing njs_vm_clone() for speed.

Dmitry Volyntsev xeioex at nginx.com
Fri Oct 25 13:20:50 UTC 2019


details:   https://hg.nginx.org/njs/rev/7e7d0dac4572
branches:  
changeset: 1202:7e7d0dac4572
user:      Dmitry Volyntsev <xeioex at nginx.com>
date:      Fri Oct 25 16:20:37 2019 +0300
description:
Optimizing njs_vm_clone() for speed.

Postponing allocation of structures where possible.

diffstat:

 src/njs_builtin.c |   34 ++++++-
 src/njs_extern.c  |   13 ++-
 src/njs_vm.c      |  224 ++++++++++++++++++-----------------------------------
 src/njs_vmcode.c  |    2 +-
 4 files changed, 120 insertions(+), 153 deletions(-)

diffs (427 lines):

diff -r d849bf348b0d -r 7e7d0dac4572 src/njs_builtin.c
--- a/src/njs_builtin.c	Thu Oct 24 16:17:17 2019 +0300
+++ b/src/njs_builtin.c	Fri Oct 25 16:20:37 2019 +0300
@@ -183,13 +183,34 @@ njs_builtin_objects_create(njs_vm_t *vm)
     njs_function_t             *func;
     njs_vm_shared_t            *shared;
     njs_lvlhsh_query_t         lhq;
+    njs_regexp_pattern_t       *pattern;
     njs_object_prototype_t     *prototype;
     const njs_object_init_t    *obj, **p;
     const njs_function_init_t  *f;
 
     static const njs_str_t  sandbox_key = njs_str("sandbox");
 
-    shared = vm->shared;
+    shared = njs_mp_zalloc(vm->mem_pool, sizeof(njs_vm_shared_t));
+    if (njs_slow_path(shared == NULL)) {
+        return NJS_ERROR;
+    }
+
+    njs_lvlhsh_init(&shared->keywords_hash);
+
+    ret = njs_lexer_keywords_init(vm->mem_pool, &shared->keywords_hash);
+    if (njs_slow_path(ret != NJS_OK)) {
+        return NJS_ERROR;
+    }
+
+    njs_lvlhsh_init(&shared->values_hash);
+
+    pattern = njs_regexp_pattern_create(vm, (u_char *) "(?:)",
+                                        njs_length("(?:)"), 0);
+    if (njs_slow_path(pattern == NULL)) {
+        return NJS_ERROR;
+    }
+
+    shared->empty_regexp_pattern = pattern;
 
     ret = njs_object_hash_init(vm, &shared->array_instance_hash,
                                &njs_array_instance_init);
@@ -242,6 +263,8 @@ njs_builtin_objects_create(njs_vm_t *vm)
         return NJS_ERROR;
     }
 
+    njs_lvlhsh_init(&vm->modules_hash);
+
     lhq.replace = 0;
     lhq.pool = vm->mem_pool;
 
@@ -302,15 +325,14 @@ njs_builtin_objects_create(njs_vm_t *vm)
     }
 
     shared->prototypes[NJS_PROTOTYPE_REGEXP].regexp.pattern =
-                                              vm->shared->empty_regexp_pattern;
+                                              shared->empty_regexp_pattern;
 
     string_object = &shared->string_object;
     njs_lvlhsh_init(&string_object->hash);
-    string_object->shared_hash = vm->shared->string_instance_hash;
+    string_object->shared_hash = shared->string_instance_hash;
     string_object->type = NJS_OBJECT_STRING;
     string_object->shared = 1;
     string_object->extensible = 0;
-    string_object->__proto__ = &vm->prototypes[NJS_PROTOTYPE_STRING].object;
 
     f = njs_native_constructors;
     func = shared->constructors;
@@ -336,6 +358,8 @@ njs_builtin_objects_create(njs_vm_t *vm)
         func++;
     }
 
+    vm->shared = shared;
+
     return NJS_OK;
 }
 
@@ -471,7 +495,7 @@ njs_builtin_objects_clone(njs_vm_t *vm, 
     }
 
     vm->global_object = vm->shared->objects[0];
-    vm->global_object.__proto__ = &vm->prototypes[NJS_PROTOTYPE_OBJECT].object;
+    vm->global_object.__proto__ = object_prototype;
     vm->global_object.shared = 0;
 
     njs_set_object(global, &vm->global_object);
diff -r d849bf348b0d -r 7e7d0dac4572 src/njs_extern.c
--- a/src/njs_extern.c	Thu Oct 24 16:17:17 2019 +0300
+++ b/src/njs_extern.c	Fri Oct 25 16:20:37 2019 +0300
@@ -171,12 +171,23 @@ njs_int_t
 njs_vm_external_create(njs_vm_t *vm, njs_value_t *ext_val,
     const njs_extern_t *proto, njs_external_ptr_t object)
 {
-    void  *obj;
+    void       *obj;
+    njs_arr_t  *externals;
 
     if (njs_slow_path(proto == NULL)) {
         return NJS_ERROR;
     }
 
+    if (njs_slow_path(vm->external_objects == NULL)) {
+        externals = njs_arr_create(vm->mem_pool, 4, sizeof(void *));
+        if (njs_slow_path(externals == NULL)) {
+            return NJS_ERROR;
+        }
+
+        vm->external_objects = externals;
+    }
+
+
     obj = njs_arr_add(vm->external_objects);
     if (njs_slow_path(obj == NULL)) {
         return NJS_ERROR;
diff -r d849bf348b0d -r 7e7d0dac4572 src/njs_vm.c
--- a/src/njs_vm.c	Thu Oct 24 16:17:17 2019 +0300
+++ b/src/njs_vm.c	Fri Oct 25 16:20:37 2019 +0300
@@ -22,11 +22,10 @@ const njs_str_t  njs_entry_anonymous =  
 njs_vm_t *
 njs_vm_create(njs_vm_opt_t *options)
 {
-    njs_mp_t              *mp;
-    njs_vm_t              *vm;
-    njs_int_t             ret;
-    njs_arr_t             *debug;
-    njs_regexp_pattern_t  *pattern;
+    njs_mp_t   *mp;
+    njs_vm_t   *vm;
+    njs_int_t  ret;
+    njs_arr_t  *debug;
 
     mp = njs_mp_fast_create(2 * njs_pagesize(), 128, 512, 16);
     if (njs_slow_path(mp == NULL)) {
@@ -34,86 +33,63 @@ njs_vm_create(njs_vm_opt_t *options)
     }
 
     vm = njs_mp_zalign(mp, sizeof(njs_value_t), sizeof(njs_vm_t));
+    if (njs_slow_path(vm == NULL)) {
+        return NULL;
+    }
 
-    if (njs_fast_path(vm != NULL)) {
-        vm->mem_pool = mp;
+    vm->mem_pool = mp;
+
+    ret = njs_regexp_init(vm);
+    if (njs_slow_path(ret != NJS_OK)) {
+        return NULL;
+    }
+
+    vm->options = *options;
+
+    if (options->shared != NULL) {
+        vm->shared = options->shared;
+
+    } else {
+        ret = njs_builtin_objects_create(vm);
+        if (njs_slow_path(ret != NJS_OK)) {
+            return NULL;
+        }
+    }
+
+    njs_lvlhsh_init(&vm->values_hash);
 
-        ret = njs_regexp_init(vm);
-        if (njs_slow_path(ret != NJS_OK)) {
+    vm->external = options->external;
+
+    vm->external_objects = njs_arr_create(vm->mem_pool, 4, sizeof(void *));
+    if (njs_slow_path(vm->external_objects == NULL)) {
+        return NULL;
+    }
+
+    njs_lvlhsh_init(&vm->externals_hash);
+    njs_lvlhsh_init(&vm->external_prototypes_hash);
+
+    vm->trace.level = NJS_LEVEL_TRACE;
+    vm->trace.size = 2048;
+    vm->trace.handler = njs_parser_trace_handler;
+    vm->trace.data = vm;
+
+    njs_set_undefined(&vm->retval);
+
+    if (options->backtrace) {
+        debug = njs_arr_create(vm->mem_pool, 4,
+                               sizeof(njs_function_debug_t));
+        if (njs_slow_path(debug == NULL)) {
             return NULL;
         }
 
-        vm->options = *options;
-
-        if (options->shared != NULL) {
-            vm->shared = options->shared;
-
-        } else {
-            vm->shared = njs_mp_zalloc(mp, sizeof(njs_vm_shared_t));
-            if (njs_slow_path(vm->shared == NULL)) {
-                return NULL;
-            }
-
-            options->shared = vm->shared;
-
-            njs_lvlhsh_init(&vm->shared->keywords_hash);
-
-            ret = njs_lexer_keywords_init(mp, &vm->shared->keywords_hash);
-            if (njs_slow_path(ret != NJS_OK)) {
-                return NULL;
-            }
-
-            njs_lvlhsh_init(&vm->shared->values_hash);
-
-            pattern = njs_regexp_pattern_create(vm, (u_char *) "(?:)",
-                                                njs_length("(?:)"), 0);
-            if (njs_slow_path(pattern == NULL)) {
-                return NULL;
-            }
-
-            vm->shared->empty_regexp_pattern = pattern;
-
-            njs_lvlhsh_init(&vm->modules_hash);
+        vm->debug = debug;
+    }
 
-            ret = njs_builtin_objects_create(vm);
-            if (njs_slow_path(ret != NJS_OK)) {
-                return NULL;
-            }
-        }
-
-        njs_lvlhsh_init(&vm->values_hash);
-
-        vm->external = options->external;
-
-        vm->external_objects = njs_arr_create(vm->mem_pool, 4, sizeof(void *));
-        if (njs_slow_path(vm->external_objects == NULL)) {
+    if (options->accumulative) {
+        ret = njs_vm_init(vm);
+        if (njs_slow_path(ret != NJS_OK)) {
             return NULL;
         }
-
-        njs_lvlhsh_init(&vm->externals_hash);
-        njs_lvlhsh_init(&vm->external_prototypes_hash);
-
-        vm->trace.level = NJS_LEVEL_TRACE;
-        vm->trace.size = 2048;
-        vm->trace.handler = njs_parser_trace_handler;
-        vm->trace.data = vm;
-
-        if (options->backtrace) {
-            debug = njs_arr_create(vm->mem_pool, 4,
-                                   sizeof(njs_function_debug_t));
-            if (njs_slow_path(debug == NULL)) {
-                return NULL;
-            }
-
-            vm->debug = debug;
-        }
-
-        if (options->accumulative) {
-            ret = njs_vm_init(vm);
-            if (njs_slow_path(ret != NJS_OK)) {
-                return NULL;
-            }
-        }
     }
 
     return vm;
@@ -243,9 +219,7 @@ njs_vm_clone(njs_vm_t *vm, njs_external_
 {
     njs_mp_t   *nmp;
     njs_vm_t   *nvm;
-    uint32_t   items;
     njs_int_t  ret;
-    njs_arr_t  *externals;
 
     njs_thread_log_debug("CLONE:");
 
@@ -258,58 +232,23 @@ njs_vm_clone(njs_vm_t *vm, njs_external_
         return NULL;
     }
 
-    nvm = njs_mp_zalign(nmp, sizeof(njs_value_t), sizeof(njs_vm_t));
-
-    if (njs_fast_path(nvm != NULL)) {
-        nvm->mem_pool = nmp;
-
-        nvm->shared = vm->shared;
-
-        nvm->trace = vm->trace;
-        nvm->trace.data = nvm;
-
-        nvm->variables_hash = vm->variables_hash;
-        nvm->values_hash = vm->values_hash;
+    nvm = njs_mp_align(nmp, sizeof(njs_value_t), sizeof(njs_vm_t));
+    if (njs_slow_path(nvm == NULL)) {
+        goto fail;
+    }
 
-        nvm->modules = vm->modules;
-        nvm->modules_hash = vm->modules_hash;
-
-        nvm->externals_hash = vm->externals_hash;
-        nvm->external_prototypes_hash = vm->external_prototypes_hash;
-
-        items = vm->external_objects->items;
-
-        externals = njs_arr_create(nvm->mem_pool, items + 4, sizeof(void *));
-        if (njs_slow_path(externals == NULL)) {
-            return NULL;
-        }
+    *nvm = *vm;
 
-        if (items > 0) {
-            memcpy(externals->start, vm->external_objects->start,
-                   items * sizeof(void *));
-            externals->items = items;
-        }
-
-        nvm->external_objects = externals;
-
-        nvm->options = vm->options;
-
-        nvm->start = vm->start;
+    nvm->mem_pool = nmp;
+    nvm->trace.data = nvm;
+    nvm->external = external;
 
-        nvm->external = external;
-
-        nvm->global_scope = vm->global_scope;
-        nvm->scope_size = vm->scope_size;
-
-        nvm->debug = vm->debug;
+    ret = njs_vm_init(nvm);
+    if (njs_slow_path(ret != NJS_OK)) {
+        goto fail;
+    }
 
-        ret = njs_vm_init(nvm);
-        if (njs_slow_path(ret != NJS_OK)) {
-            goto fail;
-        }
-
-        return nvm;
-    }
+    return nvm;
 
 fail:
 
@@ -325,7 +264,6 @@ njs_vm_init(njs_vm_t *vm)
     size_t       size, scope_size;
     u_char       *values;
     njs_int_t    ret;
-    njs_arr_t    *backtrace;
     njs_value_t  *global;
     njs_frame_t  *frame;
 
@@ -353,10 +291,7 @@ njs_vm_init(njs_vm_t *vm)
 
     vm->scopes[NJS_SCOPE_GLOBAL] = (njs_value_t *) values;
 
-    if (vm->global_scope != 0) {
-        memcpy(values + NJS_INDEX_GLOBAL_OFFSET, vm->global_scope,
-               vm->scope_size);
-    }
+    memcpy(values + NJS_INDEX_GLOBAL_OFFSET, vm->global_scope, vm->scope_size);
 
     ret = njs_regexp_init(vm);
     if (njs_slow_path(ret != NJS_OK)) {
@@ -373,20 +308,6 @@ njs_vm_init(njs_vm_t *vm)
     njs_lvlhsh_init(&vm->events_hash);
     njs_queue_init(&vm->posted_events);
 
-    if (vm->debug != NULL) {
-        backtrace = njs_arr_create(vm->mem_pool, 4,
-                                   sizeof(njs_backtrace_entry_t));
-        if (njs_slow_path(backtrace == NULL)) {
-            return NJS_ERROR;
-        }
-
-        vm->backtrace = backtrace;
-    }
-
-    if (njs_is_null(&vm->retval)) {
-        njs_set_undefined(&vm->retval);
-    }
-
     return NJS_OK;
 }
 
@@ -1101,6 +1022,7 @@ njs_int_t
 njs_vm_add_backtrace_entry(njs_vm_t *vm, njs_frame_t *frame)
 {
     njs_int_t              ret;
+    njs_arr_t              *backtrace;
     njs_uint_t             i;
     njs_function_t         *function;
     njs_native_frame_t     *native_frame;
@@ -1108,6 +1030,16 @@ njs_vm_add_backtrace_entry(njs_vm_t *vm,
     njs_function_lambda_t  *lambda;
     njs_backtrace_entry_t  *be;
 
+    if (njs_slow_path(vm->backtrace == NULL)) {
+        backtrace = njs_arr_create(vm->mem_pool, 4,
+                                   sizeof(njs_backtrace_entry_t));
+        if (njs_slow_path(backtrace == NULL)) {
+            return NJS_ERROR;
+        }
+
+        vm->backtrace = backtrace;
+    }
+
     native_frame = &frame->native;
     function = native_frame->function;
 
diff -r d849bf348b0d -r 7e7d0dac4572 src/njs_vmcode.c
--- a/src/njs_vmcode.c	Thu Oct 24 16:17:17 2019 +0300
+++ b/src/njs_vmcode.c	Fri Oct 25 16:20:37 2019 +0300
@@ -896,7 +896,7 @@ error:
         if (catch != NULL) {
             pc = catch;
 
-            if (vm->debug != NULL) {
+            if (vm->backtrace != NULL) {
                 njs_arr_reset(vm->backtrace);
             }
 


More information about the nginx-devel mailing list