summaryrefslogtreecommitdiff
path: root/hash.c
diff options
context:
space:
mode:
authorJean Boussier <[email protected]>2024-03-25 13:03:14 +0100
committerJean Boussier <[email protected]>2024-07-08 12:24:33 +0200
commit9594db0cf28d7bc10bfc46142239191a11f1dbbe (patch)
treeb7818d1a33100604a0bf9a6a1ff0a08a196b816a /hash.c
parentbfb8cad771aac8bc048fcd83e244bfe782d182e7 (diff)
Implement Hash.new(capacity:)
[Feature #19236] When building a large hash, pre-allocating it with enough capacity can save many re-hashes and significantly improve performance. ``` /opt/rubies/3.3.0/bin/ruby --disable=gems -rrubygems -I./benchmark/lib ./benchmark/benchmark-driver/exe/benchmark-driver \ --executables="compare-ruby::../miniruby-master -I.ext/common --disable-gem" \ --executables="built-ruby::./miniruby --disable-gem" \ --output=markdown --output-compare -v $(find ./benchmark -maxdepth 1 -name 'hash_new' -o -name '*hash_new*.yml' -o -name '*hash_new*.rb' | sort) compare-ruby: ruby 3.4.0dev (2024-03-25T11:48:11Z master f53209f023) +YJIT dev [arm64-darwin23] last_commit=[ruby/irb] Cache RDoc::RI::Driver.new (https://github.com/ruby/irb/pull/911) built-ruby: ruby 3.4.0dev (2024-03-25T15:29:40Z hash-new-rb 77652b08a2) +YJIT dev [arm64-darwin23] warming up... | |compare-ruby|built-ruby| |:-------------------|-----------:|---------:| |new | 7.614M| 5.976M| | | 1.27x| -| |new_with_capa_1k | 13.931k| 15.698k| | | -| 1.13x| |new_with_capa_100k | 124.746| 148.283| | | -| 1.19x| ```
Diffstat (limited to 'hash.c')
-rw-r--r--hash.c63
1 files changed, 19 insertions, 44 deletions
diff --git a/hash.c b/hash.c
index f34f64065b..cca2790dee 100644
--- a/hash.c
+++ b/hash.c
@@ -48,6 +48,7 @@
#include "ruby/thread_native.h"
#include "ruby/ractor.h"
#include "vm_sync.h"
+#include "builtin.h"
/* Flags of RHash
*
@@ -1762,58 +1763,31 @@ set_proc_default(VALUE hash, VALUE proc)
RHASH_SET_IFNONE(hash, proc);
}
-/*
- * call-seq:
- * Hash.new(default_value = nil) -> new_hash
- * Hash.new {|hash, key| ... } -> new_hash
- *
- * Returns a new empty +Hash+ object.
- *
- * The initial default value and initial default proc for the new hash
- * depend on which form above was used. See {Default Values}[rdoc-ref:Hash@Default+Values].
- *
- * If neither an argument nor a block given,
- * initializes both the default value and the default proc to <tt>nil</tt>:
- * h = Hash.new
- * h.default # => nil
- * h.default_proc # => nil
- *
- * If argument <tt>default_value</tt> given but no block given,
- * initializes the default value to the given <tt>default_value</tt>
- * and the default proc to <tt>nil</tt>:
- * h = Hash.new(false)
- * h.default # => false
- * h.default_proc # => nil
- *
- * If a block given but no argument, stores the block as the default proc
- * and sets the default value to <tt>nil</tt>:
- * h = Hash.new {|hash, key| "Default value for #{key}" }
- * h.default # => nil
- * h.default_proc.class # => Proc
- * h[:nosuch] # => "Default value for nosuch"
- */
-
static VALUE
-rb_hash_initialize(int argc, VALUE *argv, VALUE hash)
+rb_hash_init(rb_execution_context_t *ec, VALUE hash, VALUE capa_value, VALUE ifnone_unset, VALUE ifnone, VALUE block)
{
rb_hash_modify(hash);
- if (rb_block_given_p()) {
- rb_check_arity(argc, 0, 0);
- SET_PROC_DEFAULT(hash, rb_block_proc());
+ if (capa_value != INT2FIX(0)) {
+ long capa = NUM2LONG(capa_value);
+ if (capa > 0 && RHASH_SIZE(hash) == 0 && RHASH_AR_TABLE_P(hash)) {
+ hash_st_table_init(hash, &objhash, capa);
+ }
}
- else {
- rb_check_arity(argc, 0, 1);
- VALUE options, ifnone;
- rb_scan_args(argc, argv, "01:", &ifnone, &options);
- if (NIL_P(ifnone) && !NIL_P(options)) {
- ifnone = options;
- rb_warn_deprecated_to_remove("3.4", "Calling Hash.new with keyword arguments", "Hash.new({ key: value })");
+ if (!NIL_P(block)) {
+ if (ifnone_unset != Qtrue) {
+ rb_check_arity(1, 0, 0);
}
- RHASH_SET_IFNONE(hash, ifnone);
+ else {
+ SET_PROC_DEFAULT(hash, block);
+ }
+ }
+ else {
+ RHASH_SET_IFNONE(hash, ifnone_unset == Qtrue ? Qnil : ifnone);
}
+ hash_verify(hash);
return hash;
}
@@ -7150,7 +7124,6 @@ Init_Hash(void)
rb_define_alloc_func(rb_cHash, empty_hash_alloc);
rb_define_singleton_method(rb_cHash, "[]", rb_hash_s_create, -1);
rb_define_singleton_method(rb_cHash, "try_convert", rb_hash_s_try_convert, 1);
- rb_define_method(rb_cHash, "initialize", rb_hash_initialize, -1);
rb_define_method(rb_cHash, "initialize_copy", rb_hash_replace, 1);
rb_define_method(rb_cHash, "rehash", rb_hash_rehash, 0);
@@ -7477,3 +7450,5 @@ Init_Hash(void)
HASH_ASSERT(sizeof(ar_hint_t) * RHASH_AR_TABLE_MAX_SIZE == sizeof(VALUE));
}
+
+#include "hash.rbinc"