Project

General

Profile

Feature #14460

Speed up `require` and reduce memory usage

Added by tenderlovemaking (Aaron Patterson) 5 months ago. Updated 5 months ago.

Status:
Closed
Priority:
Normal
Assignee:
-
Target version:
-
[ruby-core:85490]

Description

Hi,

I've attached a patch that speeds up require and reduces memory usage. Before this patch, we could copy copy keys using rb_strdup for the loaded_features_index table. This patch changes the hash population functions to just index in to the Ruby strings without copying them. Some of the keys for the index require that the file names do not have a file extension. For that case, I create a new string (so that it's NULL padded), then index in to that string. Rather than coping the string for each / in the path, this patch just indexes in to the string. It relies on the loaded features array and the new array I introduced for liveness. get_loaded_features_index handles cache invalidation, so I believe it is safe to rely on these two arrays for liveness of the loaded_features_index keys.

I tested memory usage by booting a Rails application in production mode (the same test I'm doing with the ISeq patches), and found that it saves about 4.2% memory (59580203 bytes in trunk, 57057395 bytes with this patch). I also found that this patch eliminated 76212 system calls (presumably calls to malloc / free for the hash table keys). Finally, I found that this patch sped up require by about 35%.

Here is a graph of the memory usage:

Memory usage during boot

Each sample is a call to malloc, so you can see from the graph that this patch reduces memory usage and system calls.

I ran the bm_require.rb benchmark to compare times:

[aaron@TC-3 ruby (no-dup-string)]$ make benchmark OPTS='-p bm_require.rb'
/Users/aaron/.rbenv/shims/ruby --disable=gems ./benchmark/driver.rb -v \
                --executables="/Users/aaron/.rbenv/shims/ruby --disable=gems -I./lib -I. -I.ext/common --disable-gem; built-ruby::./miniruby -I./lib -I. -I.ext/common  --disable-gem" \
                --pattern='bm_' --directory=./benchmark -p bm_require.rb
2018-02-09 16:25:37 -0800
target 0: ruby 2.6.0dev (2018-02-07 trunk 62271) [x86_64-darwin17] at "/Users/aaron/.rbenv/shims/ruby --disable=gems -I./lib -I. -I.ext/common --disable-gem"
target 1: built-ruby (ruby 2.6.0dev (2018-02-07 trunk 62271) [x86_64-darwin17]) at "./miniruby -I./lib -I. -I.ext/common  --disable-gem"
measure target: real

-----------------------------------------------------------
require

$:.push File.join(File.dirname(__FILE__), "bm_require.data")

1.upto(10000) do |i|
  require "c#{i}"
end

$:.pop

ruby 2.6.0dev (2018-02-07 trunk 62271) [x86_64-darwin17]    3.043203999997786
built-ruby  1.9892130000007455

-----------------------------------------------------------
raw data:

[["require", [[3.043203999997786], [1.9892130000007455]]]]

Elapsed time: 5.036855 (sec)
-----------------------------------------------------------
benchmark results:
Execution time (sec)
name    ruby 2.6.0dev (2018-02-07 trunk 62271) [x86_64-darwin17]    built-ruby
require                                                    3.043         1.989

Speedup ratio: compare with the result of `ruby 2.6.0dev (2018-02-07 trunk 62271) [x86_64-darwin17]' (greater is better)
name    built-ruby
require      1.530

Log file: bmlog-20180209-162537.60174.tsv

Related issues

Related to Ruby trunk - Feature #8158: lightweight structure for loaded features indexClosed

History

#2 [ruby-core:85525] Updated by tenderlovemaking (Aaron Patterson) 5 months ago

Hi,

I didn't see that ticket, but I made a comparison now:

Updated heap comparison

They are very close. My patch ends slightly larger 56867086 bytes vs 56502412 bytes. I like you patch much more. I think Matz offered you commit access in that ticket. Are you going to accept it? If so, I think you should apply that patch. If not, I will apply your patch.

Thanks!

#3 Updated by duerst (Martin Dürst) 5 months ago

  • Related to Feature #8158: lightweight structure for loaded features index added

#4 [ruby-core:85544] Updated by funny_falcon (Yura Sokolov) 5 months ago

Aaron, while I'm going to accept commit right, I'm asking you to apply my patch.

With regards,
Yura.

#5 [ruby-core:85555] Updated by tenderlovemaking (Aaron Patterson) 5 months ago

  • Status changed from Open to Closed

Fixed in r62404. See Feature #8158

Also available in: Atom PDF