[njs] Improved memory footprint of RegExp.prototype.replace().

Dmitry Volyntsev xeioex at nginx.com
Wed Oct 4 20:55:00 UTC 2023


details:   https://hg.nginx.org/njs/rev/cf85d0f8640a
branches:  
changeset: 2214:cf85d0f8640a
user:      Dmitry Volyntsev <xeioex at nginx.com>
date:      Tue Oct 03 18:09:06 2023 -0700
description:
Improved memory footprint of RegExp.prototype.replace().

diffstat:

 src/njs_flathsh.c |   9 +++++++++
 src/njs_flathsh.h |   1 +
 src/njs_regexp.c  |  50 ++++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 60 insertions(+), 0 deletions(-)

diffs (104 lines):

diff -r a6410aad6eab -r cf85d0f8640a src/njs_flathsh.c
--- a/src/njs_flathsh.c	Tue Oct 03 00:39:04 2023 -0700
+++ b/src/njs_flathsh.c	Tue Oct 03 18:09:06 2023 -0700
@@ -162,6 +162,15 @@ njs_flathsh_new(njs_flathsh_query_t *fhq
 }
 
 
+void
+njs_flathsh_destroy(njs_flathsh_t *fh, njs_flathsh_query_t *fhq)
+{
+    njs_flathsh_free(fhq, njs_flathsh_chunk(fh->slot));
+
+    fh->slot = NULL;
+}
+
+
 static njs_flathsh_descr_t *
 njs_flathsh_alloc(njs_flathsh_query_t *fhq, size_t hash_size, size_t elts_size)
 {
diff -r a6410aad6eab -r cf85d0f8640a src/njs_flathsh.h
--- a/src/njs_flathsh.h	Tue Oct 03 00:39:04 2023 -0700
+++ b/src/njs_flathsh.h	Tue Oct 03 18:09:06 2023 -0700
@@ -130,6 +130,7 @@ NJS_EXPORT njs_flathsh_elt_t *njs_flaths
     njs_flathsh_query_t *fhq);
 
 NJS_EXPORT njs_flathsh_descr_t *njs_flathsh_new(njs_flathsh_query_t *fhq);
+NJS_EXPORT void njs_flathsh_destroy(njs_flathsh_t *fh, njs_flathsh_query_t *fhq);
 
 
 /* Temporary backward compatibility .*/
diff -r a6410aad6eab -r cf85d0f8640a src/njs_regexp.c
--- a/src/njs_regexp.c	Tue Oct 03 00:39:04 2023 -0700
+++ b/src/njs_regexp.c	Tue Oct 03 18:09:06 2023 -0700
@@ -1182,6 +1182,50 @@ done:
 }
 
 
+static void
+njs_regexp_exec_result_free(njs_vm_t *vm, njs_array_t *result)
+{
+    njs_uint_t          n;
+    njs_value_t         *start;
+    njs_flathsh_t       *hash;
+    njs_object_prop_t   *prop;
+    njs_lvlhsh_each_t   lhe;
+    njs_lvlhsh_query_t  lhq;
+
+    if (result->object.fast_array) {
+        start = result->start;
+
+        for (n = 0; n < result->length; n++) {
+            if (start[n].short_string.size == NJS_STRING_LONG) {
+                njs_mp_free(vm->mem_pool, start[n].long_string.data);
+            }
+        }
+    }
+
+    njs_lvlhsh_each_init(&lhe, &njs_object_hash_proto);
+
+    hash = &result->object.hash;
+
+    for ( ;; ) {
+        prop = njs_flathsh_each(hash, &lhe);
+
+        if (prop == NULL) {
+            break;
+        }
+
+        njs_mp_free(vm->mem_pool, prop);
+    }
+
+
+    lhq.pool = vm->mem_pool;
+    lhq.proto = &njs_object_hash_proto;
+
+    njs_flathsh_destroy(hash, &lhq);
+
+    njs_array_destroy(vm, result);
+}
+
+
 njs_int_t
 njs_regexp_prototype_exec(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs,
     njs_index_t unused, njs_value_t *retval)
@@ -1497,6 +1541,10 @@ njs_regexp_prototype_symbol_replace(njs_
                                               arguments, ncaptures, &groups,
                                               replace, retval);
 
+            if (njs_object_slots(r)) {
+                njs_regexp_exec_result_free(vm, njs_array(r));
+            }
+
         } else {
             ret = njs_array_expand(vm, array, 0,
                                    njs_is_defined(&groups) ? 3 : 2);
@@ -1517,6 +1565,8 @@ njs_regexp_prototype_symbol_replace(njs_
                                     arguments, n, retval);
         }
 
+        njs_array_destroy(vm, array);
+
         if (njs_slow_path(ret == NJS_ERROR)) {
             return NJS_ERROR;
         }


More information about the nginx-devel mailing list