2022/07/06

GAEのインスタンス起動時間

動機

GAEのスタンダード環境では、言語によってインスタンスの起動時間に差があるのは、Java8を含む第1世代VMを利用している人には、良く知られた事実です。既に起動しているインスタンスがあっても、リクエストが増えて新たにインスタンスが起動される場合にも、この起動時間がかかります。そのためインスタンス起動が遅いと、時々レスポンスが悪く感じることになります。

昨年公式に公開されたJava17がいつの間にかGAEでもプレビュー版として使えるようになっていましたので、バージョンアップで起動時間がどう変化したか確かめてみたくなりました。それにSpringの起動時間も気になります。で、言語とそのバージョン + Webフレームワークの違いで、実際のインスタンス起動時間を計ってみました。


最初に断っておきますが、私が使用する(可能性のある)組み合わせのみの測定です。


測定条件・方法

  • 基本的にアプリはGoogleのサンプルに入っていたHelloWorld、それに最低限のログを加えたもの。
  • ただしJava8/Goは手元にあった単純なアプリ。Slim3やObjectifyなどは入っていないので、結果には影響しないはず。
  • SpringBootはGoogleのサンプルに入っていたHelloWorldそのままなので、バージョンは2.6.6。
  • GoのフレームワークはGin。
  • インスタンスクラスはF1。
  • インスタンスが立ち上がっていないことをGCPコンソールで確認してから、ブラウザからリクエスト開始。
  • Cloud Loggingに記録されたログにより、リクエストの到着から、リクエストハンドラの先頭に入れたログが出るまでの時間を計算。
  • それぞれ5回測定し、平均値を算出。
  • 1回測定ごとにGCPコンソールから手動でインスタンスを停止。次の実行まで数分間放置。

測定結果

フレームワーク
なしあり
言語Java82.063-
Java111.0553.737
Java170.9393.551
Go 1.160.1760.205

単位はms。


所感

Java8

過去の経験から3秒くらいと思っていたのですが、なんか早いという結果になりました。意外でしたが、ちょっと嬉しい。

Java11

VMの起動が早いのでしょうか。フレームワークなしならVM起動してても、ほとんど待たされている感覚はありません。PHP/Pythonと同じくらいの起動時間だと思われます。


Java17

まだプレビュー版であることはご理解ください。しかしJava11より少し早くなっているのはいいですね。


SpringBoot

JavaVMに1秒+Springに3秒弱という結果でした。ブラウザを触っていても「あれ、遅いかな」と感じたころに応答が描画される感じです。これだけで十分「使えない」と判断できます。
起動時間の4秒というのは、GAEのJavaというと8しかなかった時代に、起動が遅いといわれていた状況よりも悪くなっています。Springはサーバレスという考えのなかった時代の、「起動しておいて口開けて待っている」ことが前提の時代の産物だけに、時代遅れの遺物になってしまった感があります。
サーバレスでやりたいなら、潔くSpringは捨てましょう。


Go

インタプリタもVMも存在しない、ネイティブ実行されるだけあって、爆速です。ブラウザを触っていても、インスタンス起動が起きていることを全く感じることがありません。


Gin

「フレームワークというよりライブラリ」と言われるだけあって、遅延は30ms程度と、ほとんど影響がありません。SpringBootと対照的な結果ですが、時代が違うのでサーバレスも考慮された結果なのかもしれません。


(2022/07/14追記)

現在、GAEのJava17はプレビューから一般提供に格上げされています。

2022/06/25

残念なレガシーバンドルサービス

GAE/JのJava17対応


(2024/02/26追記)
本記事の内容はすでに古くなっています。また最初の公開時に記載内容に間違いがあった可能性があります。


 久しぶりにApp Engineのドキュメントを見たら、まだプレビュー版ですが、Java17の対応が載っていて驚きました。Java17って去年秋にリリースされたばかりなので、GCPの対応はまだ先かなと想像していたのですが、予想よりずっと早いようです。Java17はJava11以来のLTSなので、注目に値します。


ランタイムの世代

GAEのランタイムには第1世代と第2世代の2種類があります。これらは実行されるランタイムのバージョンが異なるだけでなく、第1世代のみGoogleが実装した拡張機能があります。
これらの拡張機能のうち、よく使われるのは以下ではないでしょうか。
  • Memcache : オンメモリのキャッシュ
  • Search API : Googleのサーチエンジンと同じ全文検索
  • Mail API : メールの送受信
  • Users API : Googleアカウントによるユーザ認証

ランタイムを選択するうえで、これらの機能が必要かどうかも分かれ目になります。

個人的にはまだ第1世代ランタイムであるJava8を使用していて、第2世代ランタイムに移行への移行はまだです。その理由がこれらの機能を使用したいからです。


代替サービス/ライブラリ

以前は第2世代ランタイムでは、前記の第1世代ランタイムでしか提供されない機能の代わりに、他のサービス/ライブラリを使用するように、Googleは説明していました。これらの代替手段は現在でも有効で、本来はこれらの代替手段で対応するものと思います。主なものは以下のとおり。 

Memcache → Memorystore (無料枠なし)
Search API → Elasticsearch
Mail API → SendGrid/Mailgun/Mailgrid など
Users API → Identity Platform/Firebase Authentication/OpenID Connect など


Memcacheは、有料のMemorystoreが嫌なら、ちょっと極端ですが諦めてもいいでしょう。

Search APIは、代わりとして気軽に使えるものが事実上ありません。

Mail APIは、SendGridのみ無料枠が用意されています。SendGridは使いやすくて性能も十分と思います。

Users APIは優秀な代替手段が用意されており、無料枠もあるので、積極的に置き換えるべきと思います。


これらのGAEの機能と同じような状況にあったのがDatastoreですが、Datastoreはすでにサービス終了しています。代わって登場したFirestoreには「Datastore互換モード」があるので、Datastoreとほぼ同じように使えます。DatastoreはJavaライブラリが使いにくいですが、Firestoreはいくらかライブラリが使いやすくなっています。個人的にはFirestoreネイティブモードに乗り換えました。


レガシーバンドルサービスの提供

Java17対応と同時に、第2世代ランタイムに「レガシーバンドルサービス」が提供されるようになっていることに気付いて2度びっくりしました。

レガシーバンドルサービス」は第2世代ランタイムから、第1世代ランタイムのこれらの拡張機能を使用するためのライブラリのようです。これを使用することで、第2世代ランタイムも第1世代ランタイムと同様に使用することが出来るようになるようです。


しかし残念なことに、一番使いたいSearch APIは提供されないようです。

Elasticsearchがあるとはいえ、ちょっと興味本位で調査したい場合や、商用であってもサービス立ち上げ直後で利益が出せるのがいつになるか不安な状態では、安くない月額固定料金のサービスへの乗り換えは厳しいです。


Googleの本音を予想

GAEの第1世代ランタイムに用意されていた拡張機能は、Googleがランタイム(Javaの場合はJavaVM)を独自拡張して実装したのではないかと想像しています (だからランタイムの存在しないGoにはこれらの拡張機能が提供されない)。

App Engineスタンダード環境のランタイム」を読んでいるとGoogleは、第1世代ランタイムを停止して第2世代ランタイムに移行させたいのではないかと思えてきます (実際すぐに第1世代ランタイムが止まることはないことは、「レガシーランタイムの長期サポート」に説明されています)。古くなったランタイムのメンテナンスが行われなくなるのは当然なのでずっと第1世代ランタイムがサポートされることはないのですが、第2世代ランタイムへの移行を促したいのは、ランタイムの独自拡張のメンテナンスも止めたいからではないでしょうか。

なかなか移行が進まない原因を探ったら第1世代ランタイムの拡張機能が原因だったから、第2世代でも利用できるように「レガシーバンドルサービス」という形で対処したものと思われます。


Search APIの代替が用意されない理由はちょっと想像できません。Googleにとっては自社製の検索エンジンの応用らしいので、技術的には用意できなくはないはずです。政治的な理由しか考えられません。Elasticsearchに誘導したい理由は何なのでしょう。

2022/06/04

vsReversiアップデート

2022/05/17に続いて、 GCPのデモとして用意していたvsReversiをアップデートしました。


アップデート内容は以下のとおりです。

  • マテリアルデザイン対応
  • モバイル対応

マテリアルデザイン対応

Angularのマテリアルデザインに対応しました。上記のキャプチャにはマテリアルデザインの個所はありませんが、全体的に見た目がちょっとAndroidアプリぽく変化しています。


モバイル対応

過去のパーションと比較して大きな違いが出るのは、上記キャプチャのゲーム画面です。モバイル対応は、スマートフォンでしか確認できていません。手元にスマートフォンしかないので、実機での確認が出来ているのはスマートフォンだけです。タブレットや機種によっては表示がおかしくなるかもしれません。