From 3b110dc594004f31db6759d13abd802db63a26c3 Mon Sep 17 00:00:00 2001 From: Peter Ohler Date: Thu, 8 Jul 2021 19:33:29 -0400 Subject: [PATCH] Fixed cache flag not honored in compat mode --- CHANGELOG.md | 5 +++++ ext/oj/compat.c | 36 ++++++++++++++++++++++-------------- ext/oj/hash.c | 34 ++++++++++++++++++++++++++++------ ext/oj/oj.c | 9 ++++++++- ext/oj/wab.c | 15 +++++++++++---- lib/oj/version.rb | 2 +- 6 files changed, 75 insertions(+), 26 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3b967015..a11fdcc7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,10 @@ # CHANGELOG +## 3.12.1 - 2021-07-09 + +- Fixed `:cache_keys` not being honored in compat mode. +- Increased the cache size. + ## 3.12.0 - 2021-07-05 - Added string and symbol caching options that give Oj about a 20% parse performance boost. diff --git a/ext/oj/compat.c b/ext/oj/compat.c index 63929ce6..a4467225 100644 --- a/ext/oj/compat.c +++ b/ext/oj/compat.c @@ -26,22 +26,30 @@ static void hash_set_cstr(ParseInfo pi, Val kval, const char *str, size_t len, c volatile VALUE rstr = oj_cstr_to_value(str, len, (size_t)pi->options.cache_str); if (Qundef == rkey) { - VALUE *slot; - - if (Yes == pi->options.sym_key) { - if (Qnil == (rkey = oj_sym_hash_get(key, klen, &slot))) { - rkey = rb_str_new(key, klen); - rkey = oj_encode(rkey); - rkey = rb_str_intern(rkey); - *slot = rkey; - rb_gc_register_address(slot); + if (Yes != pi->options.cache_keys) { + rkey = rb_str_new(key, klen); + rkey = oj_encode(rkey); + if (Yes == pi->options.sym_key) { + rkey = rb_str_intern(rkey); } } else { - if (Qnil == (rkey = oj_str_hash_get(key, klen, &slot))) { - rkey = rb_str_new(key, klen); - rkey = oj_encode(rkey); - *slot = rkey; - rb_gc_register_address(slot); + VALUE *slot; + + if (Yes == pi->options.sym_key) { + if (Qnil == (rkey = oj_sym_hash_get(key, klen, &slot))) { + rkey = rb_str_new(key, klen); + rkey = oj_encode(rkey); + rkey = rb_str_intern(rkey); + *slot = rkey; + rb_gc_register_address(slot); + } + } else { + if (Qnil == (rkey = oj_str_hash_get(key, klen, &slot))) { + rkey = rb_str_new(key, klen); + rkey = oj_encode(rkey); + *slot = rkey; + rb_gc_register_address(slot); + } } } } diff --git a/ext/oj/hash.c b/ext/oj/hash.c index bc9d4ff4..92f5ae45 100644 --- a/ext/oj/hash.c +++ b/ext/oj/hash.c @@ -5,8 +5,8 @@ #include -#define HASH_MASK 0x000003FF -#define HASH_SLOT_CNT 1024 +#define HASH_SLOT_CNT ((uint32_t)8192) +#define HASH_MASK (HASH_SLOT_CNT - 1) typedef struct _keyVal { struct _keyVal *next; @@ -104,8 +104,8 @@ static VALUE hash_get(Hash hash, const char *key, size_t len, VALUE **slotp, VAL } void oj_hash_print() { - int i; - KeyVal b; + uint32_t i; + KeyVal b; for (i = 0; i < HASH_SLOT_CNT; i++) { printf("%4d:", i); @@ -116,6 +116,29 @@ void oj_hash_print() { } } +void oj_hash_sizes() { + uint32_t i; + KeyVal b; + int max = 0; + int min = 1000000; + + for (i = 0; i < HASH_SLOT_CNT; i++) { + int cnt = 0; + + for (b = str_hash.slots + i; 0 != b && 0 != b->key; b = b->next) { + cnt++; + } + // printf(" %4d\n", cnt); + if (max < cnt) { + max = cnt; + } + if (cnt < min) { + min = cnt; + } + } + printf("min: %d max: %d\n", min, max); +} + VALUE oj_class_hash_get(const char *key, size_t len, VALUE **slotp) { return hash_get(&class_hash, key, len, slotp, Qnil); @@ -131,8 +154,7 @@ oj_sym_hash_get(const char *key, size_t len, VALUE **slotp) { return hash_get(&sym_hash, key, len, slotp, Qnil); } -ID -oj_attr_hash_get(const char *key, size_t len, ID **slotp) { +ID oj_attr_hash_get(const char *key, size_t len, ID **slotp) { return (ID)hash_get(&intern_hash, key, len, (VALUE **)slotp, 0); } diff --git a/ext/oj/oj.c b/ext/oj/oj.c index 22364fdc..480bbd30 100644 --- a/ext/oj/oj.c +++ b/ext/oj/oj.c @@ -1673,13 +1673,20 @@ extern VALUE oj_optimize_rails(VALUE self); /* extern void oj_hash_test(); - static VALUE hash_test(VALUE self) { oj_hash_test(); return Qnil; } */ +/* +extern void oj_hash_sizes(); +static VALUE +hash_test(VALUE self) { + oj_hash_sizes(); + return Qnil; +} +*/ static VALUE protect_require(VALUE x) { rb_require("time"); diff --git a/ext/oj/wab.c b/ext/oj/wab.c index 6096058f..44e9dd3a 100644 --- a/ext/oj/wab.c +++ b/ext/oj/wab.c @@ -293,7 +293,7 @@ void oj_dump_wab_val(VALUE obj, int depth, Out out) { ///// load functions ///// -static VALUE oj_hash_key(Val parent) { +static VALUE calc_hash_key(ParseInfo pi, Val parent) { volatile VALUE rkey = parent->key_val; if (Qundef != rkey) { @@ -302,6 +302,13 @@ static VALUE oj_hash_key(Val parent) { return rkey; } + if (Yes != pi->options.cache_keys) { + rkey = rb_str_new(parent->key, parent->klen); + rkey = oj_encode(rkey); + rkey = rb_str_intern(rkey); + + return rkey; + } VALUE *slot; if (Qnil == (rkey = oj_sym_hash_get(parent->key, parent->klen, &slot))) { @@ -509,7 +516,7 @@ static VALUE start_hash(ParseInfo pi) { static void hash_set_cstr(ParseInfo pi, Val parent, const char *str, size_t len, const char *orig) { volatile VALUE rval = cstr_to_rstr(pi, str, len); - rb_hash_aset(stack_peek(&pi->stack)->val, oj_hash_key(parent), rval); + rb_hash_aset(stack_peek(&pi->stack)->val, calc_hash_key(pi, parent), rval); if (Yes == pi->options.trace) { oj_trace_parse_call("set_string", pi, __FILE__, __LINE__, rval); } @@ -522,14 +529,14 @@ static void hash_set_num(ParseInfo pi, Val parent, NumInfo ni) { oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "not a number or other value"); } rval = oj_num_as_value(ni); - rb_hash_aset(stack_peek(&pi->stack)->val, oj_hash_key(parent), rval); + rb_hash_aset(stack_peek(&pi->stack)->val, calc_hash_key(pi, parent), rval); if (Yes == pi->options.trace) { oj_trace_parse_call("set_number", pi, __FILE__, __LINE__, rval); } } static void hash_set_value(ParseInfo pi, Val parent, VALUE value) { - rb_hash_aset(stack_peek(&pi->stack)->val, oj_hash_key(parent), value); + rb_hash_aset(stack_peek(&pi->stack)->val, calc_hash_key(pi, parent), value); if (Yes == pi->options.trace) { oj_trace_parse_call("set_value", pi, __FILE__, __LINE__, value); } diff --git a/lib/oj/version.rb b/lib/oj/version.rb index a0dcaef0..9b896780 100644 --- a/lib/oj/version.rb +++ b/lib/oj/version.rb @@ -1,5 +1,5 @@ module Oj # Current version of the module. - VERSION = '3.12.0' + VERSION = '3.12.1' end