Upgrade to Pro — share decks privately, control downloads, hide ads and more …

コンパイルって結局何してるの? 〜Dartのソースコードが動くまでを覗いてみた〜

Sponsored · SiteGround - Reliable hosting with speed, security, and support you can count on.

コンパイルって結局何してるの? 〜Dartのソースコードが動くまでを覗いてみた〜

2026/09/01-03 開催の「DroidKaigi 2026」ポスターセッションで発表した資料です。

株式会社ZOZO
ブランドソリューション開発本部
新規事業部 フロントエンドブロック
大野 純平

#DroidKaigi

Avatar for ZOZO Developers

ZOZO Developers PRO

September 01, 2026

More Decks by ZOZO Developers

Other Decks in Technology

Transcript

  1. ZOZO, Inc. コンパイルって結局何してるの? Jumpei Ohno 2026.09.01 〜 Dartのソースコードが動くまでを覗いてみた 〜 f

    l u t t e r b u i l d を 叩 く と 、 D a r t の コ ー ド は 機 械 語 に な っ て 1 つ の フ ァ イ ル に 詰 め 直 さ れ る 。 そ の 「 変 換 」 の 中 身 を 、 実 際 に コ ン パ イ ル を 走 ら せ て n m や x xd で 確 か め た 。 1 ①②のコンパイルは開発者のマシンで1回だけ走り、③〜⑥のレンダリングは端末で毎フレーム走る。同じコードの話でも、動く場所も回数も違う。 ビルド時 リリースはAOTで1回、開発中はJITで毎回。だからホットリロードが効く ロ D a r t ソ ース コ ー ド 開発中は Text ( ' h e l l o ' ) 含 む 全 コ ー ド リ .dill(カ ネ ) ー AOT g _s ps (-- g = ル コンパイル en na hot tar et flutter ra ndroid tar ) な et flutter を つ フ ら の a h be in i は同じ 自分が書いた rame 違うだけで中身 nmで確 (4 ン シン } カ ネ 8,62 ,248 B → ,844,664 B ボ 構 ル ル 1 機械語 1 AOTとJITはいつ変換す かが違う (1回) ネ ティブ ままず 行(速い) AOT JIT 行し が 少しず (ホット ロ 可能) =AO 出 前 地図 部印刷 JI 歩き が 都度調べ イ 実 Tは 発 に な を全 ー lib pp.s o ( アプ リ 固有 ) iOS 向 け =AAB 公 用 ォ 開 フ App.f mewo k ( アプ リ 固有 ) ra ーマ ット で、 ン Flu e .f mewo k (エ ジ 共通) tt r ra ン ッ アセ ト + コード署 + r ン APK 生成 署名 G g P y 委ね の と を oo le la に は Elemen る。 P yが la 端末 、 が F Widge t lutterの 出典: cs. do Elemen t Rende Objec t r 3層構造( build 時 左 に . v/ s c s/ c flutter de re our e ar Elemen t hite から c r t 右へ t r -v v w るの る 4 具体例 Rende Objec t 変換 tural o er And oidはse Te x ()等で直接書き換え 。 パー の Rende Objec t r ) t り直 の tt は実 で hot indを変 na で は る t tt 自分 art t arm I PA ara で毎回コンパイル 走る。 動 は や en るだけで na 数の場所を hotは を 示す ける。 (AA B相当 な ) ar ル リも の るの て実 を 1 と 。全 つため、 れると れ リ ので イ なら の la 端末に う1つだけを る。 の になる し を って 配信す ( OS 相当物 し) る i に な が 用語: Elemen W g が 体化し スタ ス 前 見比べ 差分 更新 id et 実 たイン フレームと ン て 用語: Rende Objec アウト計算 描画 担当 必要 部分 再計算 き r 。 F me N り直 し ても 軽い 同じイン と な F me N+1 だけを だけ w ra で hei ht を る 持 実際に スタ ス 使い す ン 。 idth g → 作 t レイ だけ ra る t ara c ra ra のコードに art がF くのは lutter こ 内部 作 で ender b e t() 見 目 指定 'hello' れだけ R O j c が作 描画す 層 r e at e に 書 Hello る た W の を 回 t はで 別スタ orld て つ 測 り、 塗 の る実 体 て 用語解説 き い文字列 な イルを 混在 き で 糖衣構文 別 書き方 省略形 書 楽 し る に る せて り 、1 つ の の くのを に tat を は flutter ただ ele flutter tion rea で 3.47. 認。 囲ん 選択 き よ 1 で確 で で る うに し た Text は 例外 で、 Rc i h Text を id et。同じ こ W g が の 行番号 / しS c A いW g たな build() id et の ) は Rc 入力 i h Text ( id う 常 なら ど 見え 実際 経由 ず選択用 別W g せ ... ... ) を ただけ t 状態 持 を て ー 。 Text ( S elessWidge 幅 合わ 折 返し 文字ず 位置 計 算し 描画 る、実際 画面 メ ジ 経路: Te x t → RichTe x t → Rende r P a r a g r a ph Widget build(BuildContext c) { return Text('hello'); } イ 端末 イル をシン lutter 軽い build() r Text の b u i l d ( ) art r ード 。 RichTe x (b sic.d : 6 49 6 ) Rende P g ph (p g ph.d :3 2 8) hello ホットリロ :差分だけ即反映 上 が 起 遅いが試行錯誤が速い m64 x64 端末に入 は1つ 11.2MB → 64版 ボ 除去し 測(3.47. ) 部入 重い AAB P yが 合 配 ど F アプ こ 分 丸ご 持 こ がアプ サ ズ 下限 。immutableで、毎フ 毎フレーム Te x ( e x .d :497) a の で木は1本で足り 。Flu e は状態が変わ たびUI記述を作り直すため、間 に Elemen を挟んで「Widge 木は使い捨 、裏 表現はキャッシュ」を成立させ い T t し 。開 る。 t ie JIT: 実行 ながらそ 場で変換 r な む aarch64 == arm64 m r た ても の 形式」 規格(Flu e 3.47.1で実測) ダーと ar t た D a r t ソ ース コ ー ド extの正体 Rich ext 3層を実際にたどれる T t 実機 A PK・ AA B (And oid) O 用語: Widge 見 目 設計図 作 し t r r OS 行 き い 始位置 関 ヘッ 索引 包 必要があ g _s ps -s ps _k え 両形式 吐き分 __TEXT __DATA 最適化し APK 作 、 tt はABIと に別ファ → とに イル エンジン → 名 構成ご ッ レーム Widge ッ 測) 1で実 機械語だけでは cffa edfe Widget 使い捨て Element キャ シュ Render bject 実体 ー t (エ ジ 共通) ン ッ + Flu e iew/Ac i i アセ ト tt rV t v t yラ + tt r 3.47. 形式は違う、中身は同じ a イ る libflu e .so + r 3 ア キテクチャ対比 Widge r ード らその + a r な リ = M ch-O (iOS) ELF (And oid) 先頭4バ ト 7f45 4c46 区画名 .text .rodata アプリ固有コードと共通エンジンは別物、最後に1つの箱へ ン And oid 向 け は Tは a っと実 つ変換 、 2 ッケ ジ グ パ ら コードの lutter ELF / M ch-O = 機械語を包む「ファ る コンパイル → ン ー た 時 main: stp x29, x30, [x15, #-0x10]! ... (4命令) ← スタック残量チェック ldr x1, [x27, #0x5838] ← 引数を積む gen_snapshot bl print ← print を呼ぶ ... (2命令) ← 戻り値の準備 ldp x29, x30, [x15], #0x10 ret main() { 等 エ ジ 連携 voidprint('hello'); の 出 き ARM64(F て Dart 実機 は $ otool -tV libapp.so イ ELF/M c -O 形式が 成) ( 認済み) r a h T。実 -- g = 版 み_ g F ック 持 ( 検証済み) lib pp.so / App.f mewo k ELF(A )/ M c -O( OS) a ード JI 行し が 順次ネ ティブ化しホット 可能 開発 (flu e un)は別経路 (同じも ) 見 目 に同じ 返すメソッ るかを etになる た ( ド . t ext d a r t :756) 「Tex widge 正体はRichTex 糖衣構文」 t tの tの 5 フレ ム 中身 ー の 毎 フレ ム4行:測る→判定→記録→GPUへ ー d wF me() が毎フレ ム呼ぶ4行 ra ra flushL y ou ー rootPipelineOwner.flushLayout(); rootPipelineOwner.flushCompositingBits(); rootPipelineOwner.flushPaint(); renderView.compositeFrame(); a アウト情報 t 必要 R な ender Ojc b e tだけレイ アウト更新 root 変更あり レイ flushComposi ing B i s 子 合成が必要 判定 t 合成 要否 t に 親 子 か の flush P in a 描画命令 スト 描画命令 P c t を i ture Ly a erに 記録 dra dra リ dra composi eF me t 出典: renderin g/ bindin g. dart 6 GPU合成 :69 -702 1 、flutter / flutter Ly ツ a er リーから Sc eneを Ly 、 はO m t eller から ia ra r 数レイ りたレイ ーに ーを り ま 描 だ Text ( ) a er1〜 ったと ころ だけ 「 t() ma わ 子が 合成が必要 下準備 「合成 必要?」 かれな るだけ e() GPU ー I r e な で FlutterもネイティブU も 最後 Sのレイヤ 枚 r wR c w wI g 通 更 し 組ん GPUへ ソ ス 1 めて 3 」と 。 eneに に 、 親 伝播 に る とめ リ イ ネ ティブUI 描画結果 最終的 OS ヤ 枚 イ く に OS のコンポジタ の のレイ も ー1 になる SurfaceFlinger(Android) Core Animation(iOS) アプ =F 結 lutterに 論: 専用 描画経路があ わ の る コンパイル は「全 けではな い エ ジ 。 Dartコード ン ンは A を機械語に ndroid して 標準 AN v W の liba の ビルド時 時 T、リリー oは を リ けて は T。 リ ード くのは コードだけ。 ン ンは ファイルで ると、 さの らに るか る 開発者のマシンで、ルドのと Tだから り indo w S 1つに詰め 」作業 ・ JI ス AO ホット ロ が効 JI ・ pp.s アプ 固有 エ ジ 別 最後 合体 ・こ 2軸 分 考え 遅 原因がどち あ 切 分 すい 1回 き 実行 開発中は at i e に けや だけ走る 端末で、毎フレーム走る リとシ で c ステ UI S urfa e に ム 描 の c が重 urfa e くので、 OS こ ポ タ の ス から ーの なって1 枚 画面 の 見 ば普通 アプ れ の になる リと同じ1 枚 のレイ 内容は自分 アプ リでも確かめられ の $ nm -D libapp.so | grep kDart _kDartIsolateSnapshotData ← アプリ固有 _kDartIsolateSnapshotInstructions ← アプリ固有のコード _kDartVmSnapshotData ← Dart VM共通 _kDartVmSnapshotInstructions ← Dart VM共通のコード る ヤ (F ー lutter 3.47. を て r 、 させる GPUへ転送し 初 ネ ティブUI(And oid: V iew / iOS: UI V iew) a は い 命令 スト 記録す 枚 Sc ま 画面 出 の 再計算 兄弟 素 ー1 Flu e : Rende V iew.composi eF me() → Impelle /Ski I p /Sk が複 ヤ 合成し OS 借 ヤ 描 tt ra 変 変 1 で確 認)