From 78418c84f1621c9a919c480d1e400f0fe4d1eca1 Mon Sep 17 00:00:00 2001 From: Maxim Zhukov Date: Sat, 20 Nov 2021 21:34:07 +0300 Subject: [PATCH 1/2] value, pack: use key length from json_object iternals MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reduce the number of strlen calls in the jansson backend. Test on my laptop (count of the instructions) Before: ❯ valgrind --tool=callgrind ./bin/test_object ==3105045== Events : Ir ==3105045== Collected : 441453 After: ❯ valgrind --tool=callgrind ./bin/test_object ==3144451== Events : Ir ==3144451== Collected : 440597 Signed-off-by: Maxim Zhukov --- src/pack_unpack.c | 3 +-- src/value.c | 28 ++++++++++++++++++---------- 2 files changed, 19 insertions(+), 12 deletions(-) diff --git a/src/pack_unpack.c b/src/pack_unpack.c index 04c116e..a796ed4 100644 --- a/src/pack_unpack.c +++ b/src/pack_unpack.c @@ -562,8 +562,7 @@ static int unpack_object(scanner_t *s, json_t *root, va_list *ap) { long unpacked = 0; if (gotopt || json_object_size(root) != key_set.size) { - json_object_foreach(root, key, value) { - key_len = strlen(key); + json_object_keylen_foreach(root, key, key_len, value) { if (!hashtable_get(&key_set, key, key_len)) { unpacked++; diff --git a/src/value.c b/src/value.c index 07af087..d5a11fe 100644 --- a/src/value.c +++ b/src/value.c @@ -191,13 +191,14 @@ int json_object_clear(json_t *json) { int json_object_update(json_t *object, json_t *other) { const char *key; + size_t key_len; json_t *value; if (!json_is_object(object) || !json_is_object(other)) return -1; - json_object_foreach(other, key, value) { - if (json_object_set_nocheck(object, key, value)) + json_object_keylen_foreach(other, key, key_len, value) { + if (json_object_setn_nocheck(object, key, key_len, value)) return -1; } @@ -222,14 +223,15 @@ int json_object_update_existing(json_t *object, json_t *other) { int json_object_update_missing(json_t *object, json_t *other) { const char *key; + size_t key_len; json_t *value; if (!json_is_object(object) || !json_is_object(other)) return -1; - json_object_foreach(other, key, value) { - if (!json_object_get(object, key)) - json_object_set_nocheck(object, key, value); + json_object_keylen_foreach(other, key, key_len, value) { + if (!json_object_getn(object, key, key_len)) + json_object_setn_nocheck(object, key, key_len, value); } return 0; @@ -250,7 +252,7 @@ int do_object_update_recursive(json_t *object, json_t *other, hashtable_t *paren return -1; json_object_keylen_foreach(other, key, key_len, value) { - json_t *v = json_object_get(object, key); + json_t *v = json_object_getn(object, key, key_len); if (json_is_object(v) && json_is_object(value)) { if (do_object_update_recursive(v, value, parents)) { @@ -352,13 +354,14 @@ void *json_object_key_to_iter(const char *key) { static int json_object_equal(const json_t *object1, const json_t *object2) { const char *key; + size_t key_len; const json_t *value1, *value2; if (json_object_size(object1) != json_object_size(object2)) return 0; - json_object_foreach((json_t *)object1, key, value1) { - value2 = json_object_get(object2, key); + json_object_keylen_foreach((json_t *)object1, key, key_len, value1) { + value2 = json_object_getn(object2, key, key_len); if (!json_equal(value1, value2)) return 0; @@ -371,13 +374,15 @@ static json_t *json_object_copy(json_t *object) { json_t *result; const char *key; + size_t key_len; json_t *value; result = json_object(); if (!result) return NULL; - json_object_foreach(object, key, value) json_object_set_nocheck(result, key, value); + json_object_keylen_foreach(object, key, key_len, value) + json_object_setn_nocheck(result, key, key_len, value); return result; } @@ -400,11 +405,14 @@ static json_t *json_object_deep_copy(const json_t *object, hashtable_t *parents) iter = json_object_iter((json_t *)object); while (iter) { const char *key; + size_t key_len; const json_t *value; key = json_object_iter_key(iter); + key_len = json_object_iter_key_len(iter); value = json_object_iter_value(iter); - if (json_object_set_new_nocheck(result, key, do_deep_copy(value, parents))) { + if (json_object_setn_new_nocheck(result, key, key_len, + do_deep_copy(value, parents))) { json_decref(result); result = NULL; break; From 586b4461e6317f93903ec034739a14955a10a33e Mon Sep 17 00:00:00 2001 From: Maxim Zhukov Date: Sat, 20 Nov 2021 22:57:10 +0300 Subject: [PATCH 2/2] tests: add some cases in fixed size test Signed-off-by: Maxim Zhukov --- test/suites/api/test_fixed_size.c | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/test/suites/api/test_fixed_size.c b/test/suites/api/test_fixed_size.c index e4495ee..4ae9e07 100644 --- a/test/suites/api/test_fixed_size.c +++ b/test/suites/api/test_fixed_size.c @@ -127,6 +127,7 @@ static void test_keylen(void) { static void test_invalid_keylen(void) { json_t *obj = json_object(); + json_t *empty_obj = json_object(); const char key[] = {'t', 'e', 's', 't', '1'}; json_object_set_new_nocheck(obj, "test1", json_true()); @@ -149,7 +150,14 @@ static void test_invalid_keylen(void) { if (!json_object_del(obj, NULL)) fail("json_object_del with NULL failed"); + if (!json_object_deln(empty_obj, key, sizeof(key))) + fail("json_object_deln with empty object failed"); + + if (!json_object_deln(obj, key, sizeof(key) - 1)) + fail("json_object_deln with incomplete key failed"); + json_decref(obj); + json_decref(empty_obj); } static void test_binary_keys(void) { @@ -166,6 +174,21 @@ static void test_binary_keys(void) { if (!json_is_true(json_object_getn(obj, (const char *)&key1, sizeof(key2)))) fail("cannot get integer key2"); + if (json_object_size(obj) != 2) + fail("binary object size missmatch"); + + if (json_object_deln(obj, (const char *)&key1, sizeof(key1))) + fail("cannot del integer key1"); + + if (json_object_size(obj) != 1) + fail("binary object size missmatch"); + + if (json_object_deln(obj, (const char *)&key2, sizeof(key2))) + fail("cannot del integer key2"); + + if (json_object_size(obj) != 0) + fail("binary object size missmatch"); + json_decref(obj); }