どうもこんにちは。
今回はアプリケーションのソースコード理解を進めている中で知らないライブラリがあったので調べてみました。
標準ライブラリって何?
標準ライブラリとは、Gemfileを通じてインストールする必要がないRubyにすでにインストールされているライブラリのことを指します。
わかりやすいものでは、CSV
ライブラリがRubyの標準ライブラリとして使用されます。これは、使用したいコントローラーやモデルのファイルの中でrequire
するだけです。
# これを記述すると
require 'csv'
class Sample
def format_export
respond_to do |format|
format.csv do
bom = "\uFEFF"
# CSVクラスを使用してコードを書くことができます。
csv_data = CSV.generate(bom) do |csv|
csv << ['タイトル', 'コメント']
end
send_data(csv_data, filename: "title_and_comment.csv")
end
end
end
end
一方で、aws-sdk
などの外部で用意されたライブラリはGemfileを使用してインストールする必要があります。
追記
@tanakam 様からの助言をいただきましたので追記します。
csv
はdefault gemと呼ばれる立ち位置のライブラリなのですが、Ruby 3.4からはbundled gemというものに変更されるので、Gemfileへの記載が必須になります。
Ruby 3.3でもGemfileに書いていないと警告が出るようです。
Ruby3.4へアップグレードする場合には忘れずにGemfileへ記述する必要がありそうですね。
objspaceって何者?
objspace
はオブジェクトスペースに関する詳細な情報を提供してくれるそうです。
このライブラリが提供しているメソッドを使用すると、メモリ使用量やオブジェクトの内部構造がわかるようです。
実際に使用しているアプリケーションのRailsコンソールで試してみました。
count_objectsメソッド
Railsアプリケーションで使用しているオブジェクトの数を出力してくれるようです。
pry(main)> ObjectSpace.count_objects
=>
{
:TOTAL=>1278918, # プロセス内の全オブジェクトの総数
:FREE=>2999, # 利用可能な(未使用の)オブジェクトスロットの数
:T_OBJECT=>82998, # 汎用オブジェクトの数
:T_CLASS=>28282, # クラスオブジェクトの数
:T_MODULE=>2729, # モジュールオブジェクトの数
:T_FLOAT=>13, # 浮動小数オブジェクトの数
:T_STRING=>313107,# 文字列オブジェクトの数
:T_REGEXP=>3944, # 正規表現オブジェクトの数
:T_ARRAY=>240731, # 配列オブジェクトの数
:T_HASH=>75570, # ハッシュオブジェクトの数
:T_STRUCT=>3177, # 構造体オブジェクトの数
:T_BIGNUM=>254, # BIGNUMオブジェクト(大きい数値を扱うオブジェクト)の数
:T_FILE=>8, # ファイルオブジェクトの数
:T_DATA=>55545, # データオブジェクトの数
:T_MATCH=>1473, # マッチデータオブジェクトの数
:T_COMPLEX=>1, # 複素数オブジェクトの数
:T_RATIONAL=>629, # 有理数オブジェクトの数
:T_SYMBOL=>8288, # シンボルオブジェクトの数
:T_IMEMO=>451172, # 内部メモリオブジェクトの数
:T_ICLASS=>7998 # 内部クラスのオブジェクトの数
}
memsize_of_allメソッド
Railsアプリケーションで使用している全てのオブジェクトのメモリ使用量を出力してくれているようです。
pry(main)> ObjectSpace.memsize_of_all
=> 88991854
memsize_ofメソッド
特定のオブジェクトのメモリ使用量も出力してくれています。
# 数字の格納された配列オブジェクト
pry(main)> ObjectSpace.memsize_of([1,2,3])
=> 40
# 数字と文字列が格納された配列オブジェクト
pry(main)> ObjectSpace.memsize_of([1,2,3,4, "AAA"])
=> 80
# Railsアプリケーションで使用しているUserオブジェクト
pry(main)> ObjectSpace.memsize_of(User)
=> 6320
オブジェクトが定義された場所を取得する
以下のようにコードを記述するとオブジェクトの定義箇所を出力できる模様です。
require 'objspace'
ObjectSpace.trace_object_allocations_start
o = Object.new # 調べたいやつ
ObjectSpace.trace_object_allocations_stop
puts ObjectSpace.allocation_sourcefile(o) # ファイル名
puts ObjectSpace.allocation_sourceline(o) # 行数
ObjectSpace.trace_object_allocations_clear
うまく使いこなせれば、アプリケーション開発でコスト最適化ができそう...?
以上