docker-composeでgoogle/cloud-sdk:emulators(firestore emulator)を利用する
docker-compose記述
version: "3" services: firestore-emulator: image: google/cloud-sdk:329.0.0-emulators ports: - 8004:8004 command: gcloud beta emulators firestore start --host-port "0.0.0.0:8004"
- これで
docker-compose up
で起動できる。 - ポートは任意(8004は俺の環境)
試行錯誤で見つけた問題点(自分の環境の場合)
APIサーバーの実行環境の所感 2020
Google App Engine
- 言語/ランタイムバージョンが限定される
- 複数バージョンをデプロイして、複数の指定バージョンを簡単に試せる
- staticファイルの配信が簡単
- Go1.9時代(第1世代GAE)はいつも使っていた
- 今はstaticファイルの配信に使う
- Firebaseホスティングは複数バージョン同時配信ができない
Google Cloud Run
- Runtimeが固定されない
- デプロイが簡単、Dockerfileがそのまま使えて嬉しい
- インスタンス起動後、10〜20分くらい生きている。その後死ぬ。
Google Cloud Run / Go
- Go 1.13以降で主に使う
- スピンアップが早い。コールドスタート早い。ちょっぱや。
- Golangのサーバーサイド開発者自体を捕獲する難易度が多少高い
- ライブラリが豊富
Google Cloud Run / Kotlin
- Kotlinしゅき。
- 今日試した
- Ktor使ってスピンアップ2.3秒、以後8ms程度が最速値(Hello Worldのテキストを返すだけ)
- まあ許せなくもない気もする
- Cloud Schedulerを用いて1分に1回pingすることで0円インスタンスを1個キープできそう
Firebase Hosting
- マイクロサービスアーキテクチャで作ったときにCloud Runのサービスルーティングに使う
- staticファイルの配信としては個人的には使いにくい
Windows環境のRobolectricでUri.toFile() KTXが正常に動作しない
問題点
- Windowsファイルシステムはドライブレター(C:とか)やパスセパレータ(¥)がLinux/Macと異なる
- Uri.fromFile()を実行したとき、ドライブレターやバッククォート(日本語だと円マーク)を含んだ文字列がURLエンコードされる
KTXのUri.toFile()を行うとどうなるか
- toFile()は単純に
Uri.path
値をFileにラップして返すだけである - Windows環境でRobolectricを使用し、Uri.fromFile().pathを取得するとnullになる
- 結果、File(null)が渡されることとなり、
UnitTestを実行しているカレントディレクトリ
と解釈され、ほとんどの場合はその後のテストが落ちる
どうしたか?
Uri.path
をチェックし、問題があるようならURLデコードを行ってからFileにラップするような拡張関数を書いてやる
internal const val SCHEME_FILE = "file://" fun Uri.toFileCompat(): File { val path = this.path ?: "" return if (path.isEmpty()) { // Windows path. val path = toString().substring(SCHEME_FILE.length) File(URLDecoder.decode(path, "UTF-8")) } else { toFile() } }
楽観的な話
- そのうち公式も直すんじゃねかな?
WindowsのNTFSはtree()が遅い
起きた事象
- Windows版Android StudioのGradle Sync(像のアイコン押すと走るやつ)が異様に遅い
- 普通に
gradlew
実行だけでも遅い - MacやUbuntuだと早い
- 具体的にはこのくらい
遅かった理由
- CIのキャッシュキーにするため、特定ファイル名のハッシュ値を計算していた
- ハッシュ計算を(やり忘れないように)gradleのビルドスクリプトの中で(常に)起動していた
- ファイル一覧を列挙するとき、(実装を面倒くさがって)fileTree()によるリポジトリの全探索を行った
- 結果として、NTFSの上でファイルツリーの単純全検索が走ることとなった
- 特に
build/
配下の検索が走ってしまったのが痛かったと思われる
改善
反省点
結論
Protocol BuffersのAndroid向け実装としてSquare Wireを採用した所感
Protocol Buffersを採用した理由
- 大量のデータを扱う処理で、画面外の情報を一時的にファイルやDBに退避したい
- ついでにIntentで渡したりするのも簡単にやりたい
- モデルの定義を簡素化したい
- 銀の弾丸を求めて色々検証した結果、Protocol Buffers+Wireプラグインに落ち着いた
Protocol Buffers公式プラグイン(javaliteとか)の採用を見送った理由
- AndroidのBundleやIntentにモデルを直接putできない
- 自分でByteArrayにエンコード/デコードしなければならない
- やってやれないことはないけどそこまで手間をかけたくない
- javalite実装が3.0.0(2016年頃)で止まっている
- Firestoreとかでまだ使われているから、何かあればメンテするとは思われるが。
Wireプラグインを採用した理由
- Proto3に対応している
- Android Parcelizeをimplしたモデルを出力してくれる
- 実装を見ると、ByteArrayにエンコード(Protocol Buffers形式として)してputしている
- kotlin-parcelizeを使うことで簡単にIntentに乗せられる
- コミット履歴からみて、アクティブにメンテされている
Wireプラグインの問題
追記: Wire プラグインの不具合
- Windows版で
import "path/to/other.proto"
のように相対パスを記述するとWindowsのセパレータ(\)として認識されないためファイルが見つからなくてビルドができない - issue: https://github.com/square/wire/issues/1325
AndroidアプリプロジェクトのJDK11対応
AndroidのJDK
- Android Studioに付属しているJDKはJava8相当
- なので、公式にはJava8でビルドするのが良いと思われる
なぜJava11対応が必要になったのか
- CircleCIが用意しているAndroidビルド用Docker Imageが突然Java11になった
- ああもうしゃーないなぁとか思いながらも、変更することにした
- RobolectricがAPI29以降Java9以上必須となっていたので、まあいい機会だと
JDKインストール
Android Studioの設定変更
- Project Structureから使用するJDKを切り替える
- デフォルトはAndroid Studio付属になっている
- build.gradleの構成?によってはProject Structureが開かない不具合があるので、その場合はDefault Project Structureで切り替え、.ideaディレクトリを削除して再度プロジェクトファイルを生成させれば良い
_JAVA_OPTIONSの設定
- 初めて知ったが、
JAVA_OPTIONS
と_JAVA_OPTIONS
は明示的に異なり、通常ユーザー向けのRuntimeは前者を、開発者向けのJDKは後者をロードする - _JAVA_OPTIONSに
-Djavax.net.ssl.trustStoreType=JKS
を追加する
robolectricの設定
sdk=28
とかで固定を入れている場合、sdk=29
に変更して実行環境を調整
CircleCI設定
circleci/android:api-30
とか切り替えちゃっていいんじゃないかな
dokka設定
- ドキュメントをdokka出力しているなら、バージョンを変更する必要がある
- JDKのClass名が変わったりとかしたので
// /build.gradle classpath "org.jetbrains.dokka:dokka-gradle-plugin:1.4.0-rc"
dokkaHtml { outputFormat = 'javadoc' outputDirectory = "$buildDir/dokka" noStdlibLink = true dokkaSourceSets { noAndroidSdkLink = true configureEach { noStdlibLink = true noJdkLink = true noAndroidSdkLink = true } } } }
メイン開発PCのパーツ交換をした
メイン開発マシンのスペックアップのため、一部のパーツを入れ替えたので今後のためにメモ。
メイン開発マシンのスペック(2017~)
基本スペック
- Ryzen 1950X
- メモリ 2400MHz / 8GB×8
- GeForce GTX 1060
- NVMe SSD 512GB×2
表OS / Windows 10 / ストレージ512GB割当
裏OS / Ubuntu 20.04 / ストレージ512GB割当
- Android(Kotlin) / Flutter / Go Serverあたりの開発に使用
- 特にAndroid Studioで顕著だが、Windowsでの動作が緩慢なため切り替える場合が多い
不満だった点
- Windows 10の動作が遅い
- Git For Windows由来のbashを使用していたが、動作が緩慢
- Android Studioのビルドが遅い
- module分割を多用するアーキテクチャなので、 ビルド速度=シングルスレッド性能 の頭打ちが気になる
アップグレード計画
乗り換え先選定
- 2017年購入時と同じく、サイコム の水冷BTOが第一候補
- 予算的にはまあギリいけるか、的な範囲
- 筐体がかっこ悪くなっている
- 追加購入して、デスクトップ2台分の接地面積を取ることも難しい
- 中古で売るにしても面倒だけが多い
- 筐体を変えない(Fractal DesignDefine R5)ため、パーツ交換を行うことにする
交換内容
- Ryzen 3950Xを導入することにした
- TRを使うと、「長く使わないともったいない」ってなってしまう
- Ryzen進化速度早いので、まあ2~3年もしたらRyzen9系に追い抜かれるだろう
- シングルスレッド性能も3950Xと3960Xはほとんど変わらない
- ソケットが異なるため、自動的にマザーボードも交換することになる
- 元々の水冷クーラーがAM4非対応(オプション別売り、終売)のため、水冷クーラーも交換することになる
- 最大メモリスロットが8スロット -> 4スロットに半減するため、メモリも交換することになる
- PCIe 4が使えることと、Windowsの動作速度向上のためストレージも買い換えることになる
- 後々グラボを載せ替えるのも面倒なので、グラフィックボードも交換しておく
- という理由でドミノ倒しのように殆どの機材が入れ替えとなる
嘆き
- タイムセールで買っておきゃよかったぁ!!!!
AmazonのタイムセールでRyzen 3950Xが3万円台になってる
— 川峠@Andriders (@eaglesakura) 2020年6月27日
最終的な構成変更
- Ryzen 1950X -> Ryzen 3950X
- 水冷クーラー Corsairの昔の -> Corsair h100i Pro RGB
- メモリ 2400MHz 8GB×8 -> 3600MHz 16×4
- マザーボード X399 Taichi -> X570 Taichi
- ストレージ NVMe 512GB×2(PCIe 3.0) -> NVMe 512×2(PCIe 4.0)
- グラボ GTX 1060 -> RTX 2080 Super