Chromium を Build して動かすまでの待ち時間を「7 時間」から「30 分」まで高速化してみる

Chromium をゼロから Build して動かしてみる という前回のブログでは、Chromium を Build して動かすという一連のフローを試してみました。

この時は、Checking out and building Chromium on Linux の手順に従って作業をしました。これは、「最新の Chromium」を Linux 上で Build する事が出来るしっかりした公式手順です。しかしながら、8core, 32GiB memory の GCP VM instance でも Build に 6-7 時間程度かかってしまうのがネックでした。

そこで今日は、Chromium を Build して動かすまでのサイクルを 30 分で試せるようにすること を目指します。7時間と比較すると約15倍の高速化です!

なお、具体的には 事前に Build 済みの Object File を GCS に置いておき、ダウンロードして再利用することで再ビルドの手間を避ける というアプローチをとります。そのため、「最新の Chromium ではなく事前に Build 済みの古い Version しか試せない」ことが欠点となります。「最新の Chromium へのコミット」などを行いたい場合には適さないアプローチでしょう。

しかしながら、「過去の Version の Chromium でも良いから、試しに Build して動かしてみたい」という場合には役立つのではないかと期待しています。

以下、ステップ 0 から順番に作業を進めてみます。

ステップ0. 事前に Chromium の Build 成果物を用意して、GCS へアップロードしておく

Chromium はまともにゼロから Build すると、とてつもなく長い時間がかかってしまいます。そこで、「事前に Chromium を Build して生成した一連の Object File 及び Binary を tar.gz にまとめたもの」を用意しておきます。これをダウンロードして利用することで、「再ビルドの手間」を省くことができるはずです。

対象の File は、chromium-dev-south37 GCS Bucket の中で chromium20201213.tar.gz という名前で配置しています(suffix は日付で、2020/12/13 時点の Chromium のコードを Build したことを示しています)。

$ gsutil ls -l gs://chromium-dev-south37/chromium20201213.tar.gz
18900879483  2020-12-13T15:56:30Z  gs://chromium-dev-south37/chromium20201213.tar.gz
TOTAL: 1 objects, 18900879483 bytes (17.6 GiB)

Public にダウンロード可能な形で公開しているので、誰でも試していただくことが可能です。ソースコードも含んでいるので、17.6GiB というかなり巨大なサイズになっています。

この後のステップでは、上記の「ソースコードと Build 成果物を tar.gz でまとめたもの」を利用して作業を進めます。

ステップ1. Linux マシンを用意する

この部分は 前回 と同様です。

GCP の Compute Engine で以下の VM Instance を立ててそこで作業を行うことにします。

  • 8core, 32GiB memory (E2, e2-standard-8)
  • 200GB SSD
  • image: Ubuntu 20.04 LTS
  • zone: asia-northeast1-b

以下のコマンドで ssh して、そこで作業を行います。

$ gcloud beta compute ssh --zone "asia-northeast1-b" <instance 名>

ステップ2. 事前に用意しておいた Chromium の一連の Build 成果物をダウンロードする

早速、ステップ0 として事前に用意しておいた「Chromium の一連の Build 成果物」をダウンロードしましょう。以下のように $ gsutil cp コマンド利用して GCS からダウンロードをします。

$ gsutil -o 'GSUtil:parallel_thread_count=1' \
   -o 'GSUtil:sliced_object_download_max_components=8' \
   cp gs://chromium-dev-south37/chromium20201213.tar.gz ./chromium20201213.tar.gz

なお、ここでは Cloud Storage のパフォーマンスを最適化する - Google Cloud Platform の推奨に従って、GSUtil:parallel_thread_count オプションや GSUtil:sliced_object_download_max_components=8 オプションを利用しています。これは、 「1つの巨大なファイルの転送」をしたい場合に推奨されるオプション として紹介されています。

上記のコマンドを実行すると、環境にもよりますが大体 3 分ほどでダウンロードが完了するはずです。

minami@chromium-dev-20210226:~$ gsutil -o 'GSUtil:parallel_thread_count=1' \
>    -o 'GSUtil:sliced_object_download_max_components=8' \
>    cp gs://chromium-dev-south37/chromium20201213.tar.gz ./chromium20201213.tar.gz
Copying gs://chromium-dev-south37/chromium20201213.tar.gz...
- [1 files][ 17.6 GiB/ 17.6 GiB]   25.7 MiB/s
Operation completed over 1 objects/17.6 GiB.

ダウンロードが終わると、 17.6 GiB の chromium20201213.tar.gz が作られているはずです。

minami@chromium-dev-20210226:~$ ls -l | grep chromium
total 18457900
-rw-rw-r-- 1 minami minami 18900879483 Feb 26 12:34 chromium20201213.tar.gz

今度は、この File を $ tar xvzf chromium20201213.tar.gz で展開します。これは大体 10-15 分程度で完了するはずです。

minami@chromium-dev-20210226:~$ time tar xvzf chromium20201213.tar.gz
chromium/
.
.
.
chromium/src/cloud_print/OWNERS
chromium/.gclient
chromium/.gclient_entries

real    15m45.171s
user    5m57.618s
sys     2m49.498s

展開が終わると、以下のように chromium directory が作られているはずです。chromium directory の中には chromium/src/out/Default directory が入っています。その中には Build 済みの Object File や chrome Binary が存在する事も確認できます。

minami@chromium-dev-20210226:~$ ls -la | grep chromium
drwxrwxr-x  4 minami minami        4096 Dec 12 12:33 chromium
-rw-rw-r--  1 minami minami 18900879483 Feb 26 12:34 chromium20201213.tar.gz

minami@chromium-dev-20210226:~$ ls chromium/src/out/
Default

minami@chromium-dev-20210226:~$ ls chromium/src/out/Default/ | grep '\.so$' | wc -l
375

minami@chromium-dev-20210226:~$ ls -la chromium/src/out/Default/chrome
-rwxrwxr-x 1 minami minami 1058842464 Dec 13 14:43 chromium/src/out/Default/chrome

ただし、この状態ではまだ chrome Binary は実行できません。実行しようとすると、以下のようにエラーが出てしまいます。

minami@chromium-dev-20210226:~$ ./chromium/src/out/Default/chrome
./chromium/src/out/Default/chrome: error while loading shared libraries: libnss3.so: cannot open shared object file: No such file or directory

ステップ3. 必要な package を install

chrome Binary 実行にはいくつか package が必要となります。

まず、python2 が必要になるので、install しておきます。

minami@chromium-dev-20210226:~$ sudo apt update -y
minami@chromium-dev-20210226:~$ sudo apt install -y python2
minami@chromium-dev-20210226:~$ which python2
/usr/bin/python2
minami@chromium-dev-20210226:~$ python2 -V
Python 2.7.18
minami@chromium-dev-20210226:~$ sudo ln -s /usr/bin/python2 /usr/local/bin/python
minami@chromium-dev-20210226:~$ which python
/usr/local/bin/python
minami@chromium-dev-20210226:~$ python -V
Python 2.7.18

次に、./build/install-build-deps.sh を実行します。これは 6 分程度で完了するはずです。

minami@chromium-dev-20210226:~/chromium/src$ time ./build/install-build-deps.sh
.
.
.
Installing locales.
Generating locales (this might take a while)...
  da_DK.UTF-8... done
  en_US.UTF-8... done
  fr_FR.UTF-8... done
  he_IL.UTF-8... done
  zh_TW.UTF-8... done
Generation complete.

real    6m10.812s
user    2m35.472s
sys     0m58.130s

これで、必要な package の install が完了しました。この状態で、試しに chrome Binary を実行してみましょう。前回のように、「headless mode での実行」を試してみます。以下のようにちゃんと動作をすることが確認できました 🎉

minami@chromium-dev-20210226:~/chromium/src$ ./out/Default/chrome --headless --disable-gpu --dump-dom https://example.com
<!DOCTYPE html>
.
.
.

ここまで、 GCP VM instance への ssh から大体 20-25 分 ほどで「chrome Binary を動かすこと」が出来ました

ステップ4. Build に必要な環境をセットアップ

さて、「ダウンロードした chrome Binary」を動かせただけでは、あまり嬉しくありません。「コードを書き換えながら、chrome を Build して実行することができる」という状態を目指します。

まず、ninja など Build に必要なツールを利用するために、depot_tools をインストールします。

minami@chromium-dev-20210226:~/chromium/src$ cd $HOME
minami@chromium-dev-20210226:~$ git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git
# PATH を通しておく
minami@chromium-dev-20210226:~$ export PATH="$PATH:${PWD}/depot_tools"

これで、gn などの Build に必要なコマンドが使えるようになります。

minami@chromium-dev-20210226:~$ which gn
/home/minami/depot_tools/gn

次に、この状態で chrome Binary の Build をしてみます。autoninja -C out/Default chrome を実行すると、既に chrome Binary は存在するため、no work to do という表示が出て 5 秒程度で終了します。

minami@chromium-dev-20210226:~$ cd chromium/src/
minami@chromium-dev-20210226:~/chromium/src$ autoninja -C out/Default chrome
ninja: Entering directory `out/Default'
ninja: no work to do.

前回と同様に、chrome/common/channel_info.cc という File を touch して timestamp を更新してみます。こうすると、更新した File (及びその File に依存した File)だけを対象に Build が行われるので、20 秒程度で chrome Binary の Build が終了します。

minami@chromium-dev-20210226:~/chromium/src$ touch chrome/common/channel_info.cc
minami@chromium-dev-20210226:~/chromium/src$ time autoninja -C out/Default chrome
ninja: Entering directory `out/Default'
[4/4] LINK ./chrome

real    0m21.574s
user    0m20.022s
sys     0m5.478s

ということで、 「コードを書き換えながら、chrome をBuild して実行することができる」という状態も実現できました!🎉

まとめ

事前に Build 済みの Object File を GCS からダウンロードすることで、再ビルドの手間を避けるアプローチを試しました。その結果、前回の「ゼロからの Build」ではトータルで 7 時間かかったのに対して、今回は 30 分程度で「Chromium を Build して動かすまでのサイクルを試す」ことが出来るようになりました。

このように、「事前に用意した Build 成果物」をうまく活用することで、再ビルドの時間的・マシン的コストは劇的に下げることができます。この記事が、Chromium を試しに触ってみることへの障壁を下げることに少しでも貢献していれば幸いです。