Ruby / Railsにおけるメモリを意識した実装

Rubyとメモリ

Rubyのクラスによっては、メモリ割り当てがないのもある。 nil, true, false, 一部のIntegerがそれにあたる。

[325] pry(main)> ObjectSpace.memsize_of(nil) 
=> 0
[328] pry(main)> ObjectSpace.memsize_of(12)
=> 0
[330] pry(main)> ObjectSpace.memsize_of(true)
=> 0
[330] pry(main)> ObjectSpace.memsize_of(false)
=> 0
[332] pry(main)> ObjectSpace.memsize_of(10000)
=> 0

Arrayの場合

[345] pry(main)> ObjectSpace.memsize_of([])
=> 40
[347] pry(main)> ObjectSpace.memsize_of([1])
=> 40
[348] pry(main)> ObjectSpace.memsize_of([1,2])
=> 40
[349] pry(main)> ObjectSpace.memsize_of([1,2,3])
=> 40
[351] pry(main)> ObjectSpace.memsize_of([1,2,3,4])
=> 40

hashの場合

[358] pry(main)> ObjectSpace.memsize_of({})
=> 232
[359] pry(main)> 
[360] pry(main)> ObjectSpace.memsize_of({a: 1})
=> 232
[361] pry(main)> ObjectSpace.memsize_of({a: 1, b: 2})
=> 232
[362] pry(main)> 
[363] pry(main)> 
[364] pry(main)> ObjectSpace.memsize_of({a: 1, b: 2, c: 3})
=> 232
[365] pry(main)> 
[366] pry(main)> ObjectSpace.memsize_of({a: 1, b: 2, c: 3, d: 4})
=> 232

Stringの場合

[372] pry(main)> ObjectSpace.memsize_of("")
=> 40
[368] pry(main)> ObjectSpace.memsize_of("aad")
=> 40
[369] pry(main)> ObjectSpace.memsize_of("aad"*12)
=> 77

Active Recordとメモリ

参照下 techracho.bpsinc.jp

Ruby開発チームは2020年12月25日、Rubyの最新メジャーリリース「Ruby 3.0.0」(以下、Ruby 3.0)を公開。Ruby 3.0はパフォーマンスの改善、並行処理、静的解析の3点を目標に開発され、「Ruby 3x3」として「Ruby 3はRuby 2の3倍速くする」ことが目標に掲げられてきた。

しかし、Rubyで最も使われるRailsのActive RecordのパフォーマンスはRails 2の時代からそれほど向上しておらず、そこがネックになっている。

生成されるオブジェクト数を比べても、最適化されたクエリであっても、生SQLよりもずっと多い。

Active Recordのモデルは機能が豊富、all, find_by, firstといったメソッドのAPIが大量にあるため、Active Recordの個別のオブジェクトはメモリに読み込まれると非常に場所を取る。Active Recordのモデルのカラムがid1つだけであってもである。このため、exists? pluckなどのなるべくActive Recordのオブジェクトを生成しないメソッドを使うのが望ましい。