Slide 1

Slide 1 text

GMOビューティー株式会社 浅山 広大 カラム追加で増える ActiveRecordの メモリサイズ イメージできますか?

Slide 2

Slide 2 text

● 1インスタンスあたり何バイト増えるのか 答え・調べ方・どんなオブジェクトが生成されるか ● Rubyのメモリのレイアウトについて Rubyのメモリ管理方法(基礎編、最近のアップデート編) 一歩目の踏み出し方 この発表の構成

Slide 3

Slide 3 text

● Railsで開発していて、メモリ効率・使用量を意識し てARインスタンスを生成するようになる ● CRubyの仕組みに興味を持つきっかけになること この発表のゴール・目的

Slide 4

Slide 4 text

特に断りのない場合 Ruby 3.0, MRI (CRuby), Rails7.1, 64bit CPU での話をしています 前提

Slide 5

Slide 5 text

🤔< clinicsって参照多いテーブルだけど   このコード、どれぐらいメモリ使用量増えるのかな? きっかけ

Slide 6

Slide 6 text

add_columnすると 何バイト増えるのか (integerの場合)

Slide 7

Slide 7 text

224バイト

Slide 8

Slide 8 text

ObjectSpace.memsize_of を使う → インスタンスが持つインスタンス変数までは追えない オブジェクトのメモリサイズの調べ方

Slide 9

Slide 9 text

ObjectSpace.reachable_objects_from を使う ● あるオブジェクトから直接辿れるオブジェクトを返す ○ 1階層しか辿れないので、探索的に取得する必要がある ○ ObjectSpace.#reachable_objects_from (Ruby 3.3 リファレンスマニュアル) ○ https://www.atdot.net/~ko1/diary/201212.html#d8 オブジェクトのメモリサイズの調べ方

Slide 10

Slide 10 text

startから辿れる全てのオブジェクトを取得 https://www.atdot.net/~ko1/diary/201212.html#d8 より引用(一部改変)

Slide 11

Slide 11 text

インスタンスのメモリサイズの調べ方 PK+timestamps のARインスタンス → 3716 byte (≒3.6KB)

Slide 12

Slide 12 text

インスタンスのメモリサイズの調べ方 integerを追加して、追加前後での比較 → 224byte 増加

Slide 13

Slide 13 text

何が増えたか

Slide 14

Slide 14 text

増えたオブジェクトを調べる integerの追加前後での比較 String (40byte), ActiveModel::Attribute::FromDatabase (72byte) ActiveModel::Type::Integer (72byte), Range (40byte)

Slide 15

Slide 15 text

増えたオブジェクトを調べる ①String ②AMの中のTypeの 中のRange

Slide 16

Slide 16 text

● ActiveModel::Attributeの内部クラス ● ActiveRecordの@attributesの@attributesに格納されている ● DBからの結果をラップする (typeを持っており、型変換も担う) ActiveModel::Attribute::FromDatabaseはどこから? 定義 取得 参考: 【Rails 6.1】AS 句で作ったカラムに DB の型情報はない - ESM アジャイル事業部 開発者ブログ

Slide 17

Slide 17 text

増えたオブジェクトを調べる ⇨ 合計で224バイト増

Slide 18

Slide 18 text

増えたオブジェクトを調べる

Slide 19

Slide 19 text

CRubyのメモリレイアウトの話

Slide 20

Slide 20 text

> Ruby で扱える全ての値はオブジェクトです ● CRubyではオブジェクトごとに RVALUEと呼ばれる固定長のメモリを割り当て (例外あり) ⇨ RVALUEによってオブジェクトの値を表現 ● RVALUEへのポインタをVALUEと呼ぶ (ポインタじゃないときあり) ● VALUEはポインタを格納するので、64bit CPUで8バイト ● RVALUEはVALUE 5つ分のサイズ (ヘッダー2つ+ボディ3つ) 8 × 5 = 40byte そもそもオブジェクトって何ですか?

Slide 21

Slide 21 text

RString構造体 ● 文字列が23バイト以内で表せる場合 → RVALUE内に埋め込み (40byte) ● 24バイト以上の場合 →  len: バイト列の長さ             ptr: バイト列 (mallocで確保される)             capa: malloc - 1 (終端文字分を引く)

Slide 22

Slide 22 text

● ● RStruct構造体を使って表現 ● bodyに3つのVALUE → 始点・終点・終点を含むかどうか RStruct構造体 (Rangeの例)

Slide 23

Slide 23 text

増えたオブジェクトを理解する ⇨ 合計で224バイト増 󰢐 󰢐

Slide 24

Slide 24 text

● ● RObject構造体を使って表現 ● インスタンス変数が3つ以下 → RObject内に埋め込み ● 4つ以上の場合 →   ivptr (配列) に値を確保 (malloc)            40(RObject) + 8×4 (ivptrで確保した配列)            ⇨ 72byte RObject構造体 (ユーザー定義クラス ActiveModel::Attribute::FromDatabaseなど )

Slide 25

Slide 25 text

増えたオブジェクトを理解する ⇨ 合計で224バイト増 󰢐 󰢐 󰢐 󰢐

Slide 26

Slide 26 text

残りの疑問

Slide 27

Slide 27 text

> Ruby で扱える全ての値はオブジェクトです ● CRubyではオブジェクトごとに RVALUEと呼ばれる固定長のメモリを割り当て (例外あり) ⇨ RVALUEによってオブジェクトの値を表現 ● RVALUEへのポインタをVALUEと呼ぶ (ポインタじゃないときあり) ● VALUEはポインタを格納するので、64bit CPUで8バイト ● RVALUEはVALUE 5つ分のサイズ (ヘッダー2つ+ボディ3つ) そもそもオブジェクトって何ですか?

Slide 28

Slide 28 text

VALUE埋め込み表現 (即値、immediate value) ● VALUEはポインタ、ではないときがある ● ポインタとしてありえない値を使って、VALUEのみで値を表現 ポインタの場合: 下位3bitは必ず0 (8の倍数) ⇨ 下位3bitに1が含まれるときは、VALUE埋め込み表現 ● 例: Fixnum (整数値) ○ VALUEの下位1bitが1のとき ○ 残りの63bitで整数値を表現 ⇨ -2^62 ~ 2^62 の範囲で表現可能 (FixnumとBignumの境目)

Slide 29

Slide 29 text

増えたオブジェクトを理解する ⇨ 合計で224バイト増 󰢐 󰢐 󰢐 󰢐 󰢐

Slide 30

Slide 30 text

特に断りのない場合 Ruby 3.0, MRI (CRuby), Rails7.1, 64bit CPU での話をしています 前提

Slide 31

Slide 31 text

● Ruby 3.2 から埋め込み表現可能な範囲が広がっています VWA (Variable Width Allocation) Optimizing Ruby’s Memory Layout: Variable Width Allocation - Shopify https://shopify.engineering/ruby-variable-width-allocation

Slide 32

Slide 32 text

VWA (Variable Width Allocation) ● Size Pool という新しい概念が増えた ○ RVALUEが格納されるslotのサイズが 40, 80, 160, 320, 640byte のどれかに ● 埋め込み可能なデータの拡張 ○ String: 615byteまで埋め込み可能に ○ Object: 78個のivarまで埋め込み可能に

Slide 33

Slide 33 text

● Rubyのウラガワ (Web+DB Press連載記事) ○ 笹田さんの連載 ○ Rubyのメモリレイアウトをベースにどんな最適化がされ てきたかを解説されてる ● RHCの参考文献を読み漁る ○ 笹田さんの活動 ○ https://github.com/ko1/rubyhackchallenge/blob/ma ster/bib.md 参考資料 (CRubyを理解する第一歩として)

Slide 34

Slide 34 text

まとめ

Slide 35

Slide 35 text

add_columnすると 何バイト増えるのか (integerの場合)

Slide 36

Slide 36 text

224バイト

Slide 37

Slide 37 text

224バイト RVALUEが4個と ivptrでVALUE 4*2個 ActiveModel::Attribute::FromDabase (40+32), ActiveModel::Type::Integer (40+32), String (40), Range(40)

Slide 38

Slide 38 text

私たちのスキーマ設計

Slide 39

Slide 39 text

おまけ

Slide 40

Slide 40 text

自己&会社紹介

Slide 41

Slide 41 text

自己紹介 浅山 広大 (asayamakk) GMOビューティーで取締役エンジニアをやってます 趣味は美容医療とキックボクシングと3Dゼルダです。

Slide 42

Slide 42 text

おトクな割引クーポンの 購入サイト "美容医療で私らしく" 美容医療の検索・予約サービ ス 予約管理から電子カルテ・ 会計までを一括管理  3 つ の 提 供 サ ー ビ ス キレイパスなら、あなたにぴったりな 施術や美容クリニックが見つかる。 チケット購入から予約まで、スムーズ な体験を提供します。 クリニックのDXを加速させ効率的な オペレーションと経営サポートを実現 する美容クリニックの経営支援プラッ トフォームです。 ビューティーサロン・ 美 容 クリニック ・グルメ・ 宿 泊 ・ 通 販 など、 様 々な ジャンルの割引クーポンを掲載中! 毎 日お昼の12時に、新 着のおトクな クーポンが登場します。

Slide 43

Slide 43 text

ブース&この後のセッションでもお会いしましょう!