[njs] Shell: simplified console.time()/timeEnd() pair.

Dmitry Volyntsev xeioex at nginx.com
Fri Sep 22 19:59:44 UTC 2023


details:   https://hg.nginx.org/njs/rev/fc98c27d3fc0
branches:  
changeset: 2205:fc98c27d3fc0
user:      Dmitry Volyntsev <xeioex at nginx.com>
date:      Thu Sep 21 12:40:53 2023 -0700
description:
Shell: simplified console.time()/timeEnd() pair.

Using a queue instead of a hash here because we assume that the
number of profile timers will be low.

diffstat:

 external/njs_shell.c |  158 +++++++++++++++++++-------------------------------
 test/shell_test.exp  |    2 +
 2 files changed, 63 insertions(+), 97 deletions(-)

diffs (256 lines):

diff -r 49f6f5c81a11 -r fc98c27d3fc0 external/njs_shell.c
--- a/external/njs_shell.c	Wed Sep 20 21:48:41 2023 -0700
+++ b/external/njs_shell.c	Thu Sep 21 12:40:53 2023 -0700
@@ -80,8 +80,9 @@ typedef struct {
 
 
 typedef struct {
-    njs_opaque_value_t      name;
+    njs_str_t               name;
     uint64_t                time;
+    njs_queue_link_t        link;
 } njs_timelabel_t;
 
 
@@ -91,7 +92,7 @@ typedef struct {
     njs_lvlhsh_t            events;  /* njs_ev_t * */
     njs_queue_t             posted_events;
 
-    njs_lvlhsh_t            labels;  /* njs_timelabel_t */
+    njs_queue_t             labels;
 
     njs_completion_t        completion;
 } njs_console_t;
@@ -136,8 +137,6 @@ static void njs_console_clear_timer(njs_
 static void njs_console_log(njs_vm_t *vm, njs_external_ptr_t external,
     njs_log_level_t level, const u_char *start, size_t length);
 
-static njs_int_t njs_timelabel_hash_test(njs_lvlhsh_query_t *lhq, void *data);
-
 static njs_int_t lvlhsh_key_test(njs_lvlhsh_query_t *lhq, void *data);
 static void *lvlhsh_pool_alloc(void *pool, size_t size);
 static void lvlhsh_pool_free(void *pool, void *p, size_t size);
@@ -275,14 +274,6 @@ static const njs_lvlhsh_proto_t  lvlhsh_
 };
 
 
-static const njs_lvlhsh_proto_t  njs_timelabel_hash_proto njs_aligned(64) = {
-    NJS_LVLHSH_DEFAULT,
-    njs_timelabel_hash_test,
-    lvlhsh_pool_alloc,
-    lvlhsh_pool_free,
-};
-
-
 static njs_vm_ops_t njs_console_ops = {
     njs_console_set_timer,
     njs_console_clear_timer,
@@ -840,8 +831,7 @@ njs_console_init(njs_vm_t *vm, njs_conso
 
     njs_lvlhsh_init(&console->events);
     njs_queue_init(&console->posted_events);
-
-    njs_lvlhsh_init(&console->labels);
+    njs_queue_init(&console->labels);
 
     console->completion.completions = njs_vm_completions(vm, NULL);
     if (console->completion.completions == NULL) {
@@ -1408,12 +1398,13 @@ static njs_int_t
 njs_ext_console_time(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs,
     njs_index_t unused, njs_value_t *retval)
 {
-    njs_int_t           ret;
-    njs_str_t           name;
-    njs_value_t         *value;
-    njs_console_t       *console;
-    njs_timelabel_t     *label;
-    njs_lvlhsh_query_t  lhq;
+    njs_int_t         ret;
+    njs_str_t         name;
+    njs_queue_t       *labels;
+    njs_value_t       *value;
+    njs_console_t     *console;
+    njs_timelabel_t   *label;
+    njs_queue_link_t  *link;
 
     static const njs_str_t  default_label = njs_str("default");
 
@@ -1441,40 +1432,31 @@ njs_ext_console_time(njs_vm_t *vm, njs_v
         njs_value_string_get(value, &name);
     }
 
+    labels = &console->labels;
+    link = njs_queue_first(labels);
+
+    while (link != njs_queue_tail(labels)) {
+        label = njs_queue_link_data(link, njs_timelabel_t, link);
+
+        if (njs_strstr_eq(&name, &label->name)) {
+            njs_vm_log(vm, "Timer \"%V\" already exists.\n", &name);
+            njs_value_undefined_set(retval);
+            return NJS_OK;
+        }
+
+        link = njs_queue_next(link);
+    }
+
     label = njs_mp_alloc(njs_vm_memory_pool(vm), sizeof(njs_timelabel_t));
     if (njs_slow_path(label == NULL)) {
         njs_vm_memory_error(vm);
         return NJS_ERROR;
     }
 
-    lhq.replace = 0;
-    lhq.key = name;
-    lhq.key_hash = njs_djb_hash(name.start, name.length);
-    lhq.value = label;
-    lhq.pool = njs_vm_memory_pool(vm);
-    lhq.proto = &njs_timelabel_hash_proto;
-
-    ret = njs_lvlhsh_insert(&console->labels, &lhq);
-
-    if (njs_fast_path(ret == NJS_OK)) {
-        (void) njs_vm_value_string_set(vm, njs_value_arg(&label->name),
-                                       name.start, name.length);
+    label->name = name;
+    label->time = njs_time();
 
-    } else {
-        njs_mp_free(njs_vm_memory_pool(vm), label);
-
-        if (njs_slow_path(ret == NJS_ERROR)) {
-            njs_vm_error(vm, "lvlhsh insert failed");
-
-            return NJS_ERROR;
-        }
-
-        njs_vm_log(vm, "Timer \"%V\" already exists.\n", &name);
-
-        label = lhq.value;
-    }
-
-    label->time = njs_time();
+    njs_queue_insert_tail(&console->labels, &label->link);
 
     njs_value_undefined_set(retval);
 
@@ -1486,13 +1468,14 @@ static njs_int_t
 njs_ext_console_time_end(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs,
     njs_index_t unused, njs_value_t *retval)
 {
-    uint64_t            ns, ms;
-    njs_int_t           ret;
-    njs_str_t           name;
-    njs_value_t         *value;
-    njs_console_t       *console;
-    njs_timelabel_t     *label;
-    njs_lvlhsh_query_t  lhq;
+    uint64_t          ns, ms;
+    njs_int_t         ret;
+    njs_str_t         name;
+    njs_queue_t       *labels;
+    njs_value_t       *value;
+    njs_console_t     *console;
+    njs_timelabel_t   *label;
+    njs_queue_link_t  *link;
 
     static const njs_str_t  default_label = njs_str("default");
 
@@ -1522,37 +1505,35 @@ njs_ext_console_time_end(njs_vm_t *vm, n
         njs_value_string_get(value, &name);
     }
 
-    lhq.key = name;
-    lhq.key_hash = njs_djb_hash(name.start, name.length);
-    lhq.pool = njs_vm_memory_pool(vm);
-    lhq.proto = &njs_timelabel_hash_proto;
-
-    ret = njs_lvlhsh_delete(&console->labels, &lhq);
-
-    if (njs_fast_path(ret == NJS_OK)) {
-
-        label = lhq.value;
-
-        ns = ns - label->time;
+    labels = &console->labels;
+    link = njs_queue_first(labels);
 
-        ms = ns / 1000000;
-        ns = ns % 1000000;
-
-        njs_vm_log(vm, "%V: %uL.%06uLms\n", &name, ms, ns);
-
-        /* GC: release. */
-        njs_mp_free(njs_vm_memory_pool(vm), label);
-
-    } else {
-        if (ret == NJS_ERROR) {
-            njs_vm_error(vm, "lvlhsh delete failed");
-
-            return NJS_ERROR;
+    for ( ;; ) {
+        if (link == njs_queue_tail(labels)) {
+            njs_vm_log(vm, "Timer \"%V\" doesn’t exist.\n", &name);
+            njs_value_undefined_set(retval);
+            return NJS_OK;
         }
 
-        njs_vm_log(vm, "Timer \"%V\" doesn’t exist.\n", &name);
+        label = njs_queue_link_data(link, njs_timelabel_t, link);
+
+        if (njs_strstr_eq(&name, &label->name)) {
+            njs_queue_remove(&label->link);
+            break;
+        }
+
+        link = njs_queue_next(link);
     }
 
+    ns = ns - label->time;
+
+    ms = ns / 1000000;
+    ns = ns % 1000000;
+
+    njs_vm_log(vm, "%V: %uL.%06uLms\n", &name, ms, ns);
+
+    njs_mp_free(njs_vm_memory_pool(vm), label);
+
     njs_value_undefined_set(retval);
 
     return NJS_OK;
@@ -1656,23 +1637,6 @@ njs_console_log(njs_vm_t *vm, njs_extern
 
 
 static njs_int_t
-njs_timelabel_hash_test(njs_lvlhsh_query_t *lhq, void *data)
-{
-    njs_str_t        str;
-    njs_timelabel_t  *label;
-
-    label = data;
-    njs_value_string_get(njs_value_arg(&label->name), &str);
-
-    if (njs_strstr_eq(&lhq->key, &str)) {
-        return NJS_OK;
-    }
-
-    return NJS_DECLINED;
-}
-
-
-static njs_int_t
 lvlhsh_key_test(njs_lvlhsh_query_t *lhq, void *data)
 {
     njs_ev_t  *ev;
diff -r 49f6f5c81a11 -r fc98c27d3fc0 test/shell_test.exp
--- a/test/shell_test.exp	Wed Sep 20 21:48:41 2023 -0700
+++ b/test/shell_test.exp	Thu Sep 21 12:40:53 2023 -0700
@@ -299,6 +299,8 @@ njs_test {
      "console.timeEnd()\r\nTimer \"default\" doesn’t exist."}
     {"console.timeEnd('abc')\r\n"
      "console.timeEnd('abc')\r\nTimer \"abc\" doesn’t exist."}
+    {"console.time('abc')\r\n"
+     "console.time('abc')\r\nundefined\r\n>> "}
 }
 
 njs_test {


More information about the nginx-devel mailing list