Age | Commit message (Collapse) | Author |
|
[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|
```
|
|
|
|
|
|
|
|
Also, refactor the cfunc struct to use a new rb_cfunc_t.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
The macro SafeStringValue() became just StringValue() in c5c05460ac2,
and it is deprecated nowadays.
This patch replaces remaining macro usage. Some occurrences are left in
ext/stringio and ext/win32ole, they should be fixed upstream.
The macro itself is not deleted, because it may be used in extensions.
|
|
|
|
[Bug #20145]
Before this commit, both copy_compare_by_id and hash_copy will create a
copy of the ST table, so the ST table created in copy_compare_by_id will
be leaked.
h = { 1 => 2 }.compare_by_identity
10.times do
1_000_000.times do
h.select { false }
end
puts `ps -o rss= -p #{$$}`
end
Before:
110736
204352
300272
395520
460704
476736
542000
604704
682624
770528
After:
15504
16048
16144
16256
16320
16320
16752
16752
16752
16752
|
|
|
|
|
|
|
|
|
|
st_replace and st_init_existing_table_with_size are functions used
internally in Ruby and should not be publicly visible.
|
|
If a Hash is non-empty, there's no point calling `ar_force_convert_table`. We'll be immediately discarding that new st table, and replacing it with the new `identtable` st table that we're stealing out of `tmp`.
|
|
For non-empty Hashes, this function needs to rehash all the stored values (using the new `compare` and `hash` functions from `identhash`). It does so by writing into a newly allocated `tmp` Hash, and then transferring ownership of its st table into `self`.
For empty Hashes, we can skip allocating this `tmp`, because there's nothing to re-hash. We can just modify our new st table's `type` in-place.
|
|
|
|
* delete `ar_try_convert` but use `ar_force_convert_table`
to make program simple.
* `ar_force_convert_table` checks hash modification while
calling `#hash` method with the following strategy:
1. copy keys (and vals) of ar_table
2. calc hashes from keys
3. check copied keys and hash's keys. if not matched, repeat from 1
fix [Bug #20050]
|
|
We didn't free the old ST before overwriting it which caused a leak.
Found with RUBY_FREE_ON_EXIT.
Co-authored-by: Peter Zhu <[email protected]>
|
|
st.c redefines malloc and free to be ruby_xmalloc and ruby_xfree, so
when this was copied into hash.c it ended up mismatching an xmalloc with
a regular free, which ended up inflating oldmalloc_increase_bytes when
hashes were freed by minor GC.
|
|
|
|
|
|
ar_table may be converted to st_table by `ar_force_convert_table`.
If the conversion occurs during the iteration of ar_table, the iteration
may lead to memory corruption.
This change prevents the catastrophy by throwing an exception when the
conversion is detected.
This issue is reported by [SuperS](https://hackerone.com/superss)
|
|
The level in ivar is no longer needed to check if iterating, only used
for increment/decrement.
|
|
- Make it unsigned like as in-flags bits
- Make it long since it should be fixable
- Reduce it to in-flags bits after decrement
|
|
|
|
|
|
|
|
|
|
|
|
We need to free the old ST table in Hash#rehash.
Co-authored-by: Adam Hess <[email protected]>
|
|
|
|
Notes:
Merged: https://github.com/ruby/ruby/pull/8357
Merged-By: nobu <[email protected]>
|
|
Notes:
Merged: https://github.com/ruby/ruby/pull/8356
Merged-By: nobu <[email protected]>
|
|
Notes:
Merged: https://github.com/ruby/ruby/pull/8211
|
|
|
|
RARRAY_PTR_USE now does the same things as RARRAY_PTR_USE_TRANSIENT.
Notes:
Merged: https://github.com/ruby/ruby/pull/8071
|
|
According to the C99 specification section 7.20.3.2 paragraph 2:
> If ptr is a null pointer, no action occurs.
So we do not need to check that the pointer is a null pointer.
Notes:
Merged: https://github.com/ruby/ruby/pull/8004
|
|
Hash#replace can leak memory if the receiver has an ST table.
Notes:
Merged: https://github.com/ruby/ruby/pull/8001
|
|
st_copy allocates a st_table, which is not needed for hashes since it is
allocated by VWA and embedded, so this causes a memory leak.
The following script demonstrates the issue:
```ruby
20.times do
100_000.times do
{a: 1, b: 2, c: 3, d: 4, e: 5, f: 6, g: 7, h: 8, i: 9}
end
puts `ps -o rss= -p #{$$}`
end
```
Notes:
Merged: https://github.com/ruby/ruby/pull/8000
|
|
Notes:
Merged: https://github.com/ruby/ruby/pull/8000
|
|
Notes:
Merged: https://github.com/ruby/ruby/pull/7976
Merged-By: nobu <[email protected]>
|
|
RHASH_TABLE_NULL_P and ar_alloc_table are no longer needed since
all Hash will have AR tables.
|
|
|
|
|