趣味的なIT・ネットの話題

TypeScriptのコンパイル(トランスパイル)が爆裂に遅いことの対策を考える

Raspberry Pi上でTypescriptのコンパイルをやってみようと思い、tscを実行してみたところ、コマンドラインにもどって来ません。あれ、コンパイラが壊れているのかなと思っていたら、その後で戻ってきます。単に時間がかかっていただけのようです。tscには計測機能がついているのでコンパイル時間を計ってみるとこの通り。

pi@raspberrypi:~/ts $ tsc --diagnostics st.ts
Files:               2
Lines:           17319
Nodes:           77389
Identifiers:     29814
Symbols:         44284
Types:            4340
Memory used:    32591K
I/O read:        0.02s
I/O write:       0.00s
Parse time:      2.20s
Bind time:       1.37s
Check time:      6.05s
Emit time:       0.23s
Total time:      9.86s

なにか凄いコードをコンパイルしたとか言うわけでは無く、公式のこの5行のコードを食わせただけです。

function greeter(person: string) {
    return "Hello, " + person;
}

var user = "Jane User";

document.body.innerHTML = greeter(user);

どうもlib.d.tsというTypeScriptのライブラリのパースとチェックに時間がかかっている模様。

tsc is slow to process lib.d.ts · Issue #3298 · Microsoft/TypeScript · GitHub

たしかに先の結果でも対象行が凄い量になっています。ライブラリをくっつけずにコンパイルするとこの通り大分と早くなります。

pi@raspberrypi:~/ts $ tsc --nolib --diagnostics st.ts
error TS2318: Cannot find global type 'Array'.
error TS2318: Cannot find global type 'Boolean'.
error TS2318: Cannot find global type 'Function'.
error TS2318: Cannot find global type 'IArguments'.
error TS2318: Cannot find global type 'Number'.
error TS2318: Cannot find global type 'Object'.
error TS2318: Cannot find global type 'RegExp'.
error TS2318: Cannot find global type 'String'.
Files:               1
Lines:              10
Nodes:              32
Identifiers:         9
Symbols:             7
Types:              15
Memory used:     9694K
I/O read:        0.00s
I/O write:       0.00s
Parse time:      0.12s
Bind time:       0.04s
Check time:      0.14s
Emit time:       0.23s
Total time:      0.53s

ただライブラリを付けないと意味が無いので、ライブラリ部分のチェックだけ外してみると最初よりは大分と早くなっています。ただ開発していてストレスがかかるレベルですね。rpi2でこれなのでrpi1とかだとどうなるんだろう。

pi@raspberrypi:~/ts $ tsc --skipDefaultLibCheck --diagnostics st.ts
Files:               2
Lines:           17319
Nodes:           77389
Identifiers:     29814
Symbols:         44111
Types:              36
Memory used:    21564K
I/O read:        0.02s
I/O write:       0.00s
Parse time:      2.19s
Bind time:       1.34s
Check time:      0.17s
Emit time:       0.23s
Total time:      3.94s

で、これではお話にならないので対策を考えることにします。rpi2に入れたnodeで動かしたいので最初からちゃんとリモートで動く環境を作りたいんです。

そもそもライブラリをチェックしたりコンパイルする必要も無いのだから、プリコンパイルしてリンクの時だけくっつけたらいいのでは無いかと思い検索したら同じ事を考えている人がいました。

How to use compiler API to hold lib.d.ts in precompiled form · Issue #2030 · Microsoft/TypeScript · GitHub

が、この方法だとソースの中身をいじる必要がありそうなのでパス。自分はそもそも今からTypeScriptを覚えようとしている段階なので、覚える前にソースをいじらないといけないというのでは順序が逆なので。

次に考えたのが、atom-typescriptにはtsの保存と同時にjsを生成する機能があるので、それを使えばいいというソリューション。自分はRemote-FTPパッケージを使っているので、もともとリモートファイルをローカルファイルの様に編集できているので、リモートのtsを編集して保存すると同時にjsができれば簡単です。が、Remote-FTPがリモートのファイルを更新してくれるのは、エディタ画面上で保存ボタンを押したときのみで、atom-typescriptが自動生成するファイルをリモートに保存してくれる訳ではありませんでした。

この延長線上で考えたのがRemote-FTPにはローカルとリモートを同期させる機能があるので、これを使うという手。しかしファイルを更新する都度syncを実行するのは面倒です。それをやっている間に3.94秒経ちそう。

でもって次に考えたのがローカルのファイル変更を検出して自動的にリモートにアップロードするという方法。調べてみるとOSXならOS標準の機能だけで実行できそうです。

OSXのLaunchAgentでホストOSのファイル監視してリモートサーバーにrsyncして同期する方法 – Qiita

が、設定ファイルを見て気が重くなったのと、ファイル変更を検知するプロセスが常駐するというのはマシンの負荷が増えそうなのが気になります。この設定をした直後はいいんですが、開発が終わったらこの設定をしたことを忘れてしまって、OSを再インストールするまで常駐しそう。

で、結局採用したのが、リモートのフォルダをそのままマウントする方法。一番ありきたりな手段に落ち着きました。

SSHFS (SSH Filesystem) – Raspberry Pi Documentation

使い方はなんてことはなくてこの通り実行するだけ。最初リモートでsshfsというサーバーが稼働するのかと思い、piの方でapt-getを実行してしまいました。これはクライアントサイドでsshをラップしてリモートをマウントしているように見せるためのものですね。

マウントするとローカルのマウントポイントの名前とアイコンが変わりました。

スクリーンショット 2016-03-05 8.11.10

マウントしてローカルのatomでtsファイルを更新したら(5行目のgreeterを康雄にしました)、リモートのjsが更新されています。

スクリーンショット 2016-03-05 8.08.47

マルチバイト文字でも問題なし。

スクリーンショット 2016-03-05 8.10.02

とりあえずこれでTypeScriptの学習を進めます。


Facebooktwitterpinterestlinkedinmail
納得したらすぐにシェア!