Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
When use non-frozen string as hash key with rb_hash_aset(), it will duplicate and freeze the string internally. ```c static int hash_aset_str(st_data_t *key, st_data_t *val, struct update_arg *arg, int existing) { if (!existing && !RB_OBJ_FROZEN(*key)) { *key = rb_hash_key_str(*key); } return hash_aset(key, val, arg, existing); } ``` Refer: https://github.com/ruby/ruby/blob/bda56a03a625793cb3fd110458c3f7323d73705e/hash.c#L2890-L2897 To avoid duplicate and freeze, this patch will give a frozen string in rb_hash_aset(). FYI) If you use string as hash key, hash object always might have frozen string as key. ``` irb(main):001:0> hash = { "foo" => 42, bar: 55 } => {"foo"=>42, :bar=>55} irb(main):002:0> hash.keys[0].frozen? => true irb(main):003:0> hash.keys[1].frozen? => true ``` This patch has same approch with flori/json#345 − | before | after | result -- | -- | -- | -- Oj.load | 335.122k | 422.081k | 1.26x ### Environment - MacBook Air (M1, 2020) - macOS 12.0 beta 3 - Apple M1 - Ruby 3.0.2 ### Before ``` Warming up -------------------------------------- Oj.load 33.829k i/100ms Calculating ------------------------------------- Oj.load 335.122k (± 0.9%) i/s - 1.691M in 5.047682s ``` ### After ``` Warming up -------------------------------------- Oj.load 42.573k i/100ms Calculating ------------------------------------- Oj.load 422.081k (± 0.5%) i/s - 2.129M in 5.043373s ``` ### Test code ```ruby require 'benchmark/ips' require 'oj' json =<<-EOF { "$id": "https://example.com/person.schema.json", "$schema": "https://json-schema.org/draft/2020-12/schema", "title": "Person", "type": "object", "properties": { "firstName": { "type": "string", "description": "The person's first name." }, "lastName": { "type": "string", "description": "The person's last name." }, "age": { "description": "Age in years which must be equal to or greater than zero.", "type": "integer", "minimum": 0 } } } EOF Benchmark.ips do |x| x.report('Oj.load') { Oj.load(json) } end ```
- Loading branch information