$shibayu36->blog;

株式会社はてなでエンジニアをしています。プログラミングや読書のことなどについて書いています。

「実践Scala入門」読んだ

実践Scala入門

実践Scala入門

読んだ。この本は「コンパクトなコップ本」を目指したと最初に書かれているとおり、この本を読めばひとまずScalaを書けるようになるなと思った。これからScalaを始めたくなったらまずはこの本を読んでおけば十分だと思う。

また、「コンパクトなコップ本」だけに留まらず、実践ではよく使うがコップ本ではあまり言及されていないような機能についても解説されていたことが非常に良かった。例えばコップ本ではOptionやEither、Tryなどを使ったエラー処理についてあまり書かれておらず、昔Scalaを始める時にエラー処理のやり方で詰まったことがあった。その時にこの本を読んでいたらもっとスタートダッシュが速かっただろうと思う。他にも実践ではほとんどの場合利用するsbtについても解説されているのも良かった。

こんな感じでScala入門するには最適な一冊だと感じました。

読書ノート

- javaでscalaのコンパイル後jarを動かす方法。scala標準ライブラリにクラスパスが通ってれば良い 20
- scalatestのscaladocは品質が高いらしい、あとで調べる 34
- オプションにnull渡すとnoneになるのでjavaライブラリをラップも出来る 104
- ジェネリックな型をサブタイプにする 109
- :で終わると右結合 130
- updateという関数は、代入で置き換えられる 140
- future周り教えてくれるのがいい。コップ本だとなかった? 158
- print:namer試したい 172
- partialfunctionにはマッチしないかもしれないパターンマッチを渡しても大丈夫 172
- sbtのビルドのスコープにはプロジェクト軸、コンフィグレーション軸、タスク軸があり、それらすべてでキーごとの値を変更可能 200
- sbtの設定できるキーの一覧は https://github.com/sbt/sbt/blob/develop/main/src/main/scala/sbt/Keys.scala で確認可能 204
- privateめそっどのテストに使えるtrait便利そう、ただパッケージプライベートで問題ないらしい 223
- AsyncFunSuite 226
- partial functionでcaseを全部書かなくて済む。isDefinedAtで呼び出しが成功するか確認可能 241
- extends AnyValして値クラスを作るとJVMレベルのオブジェクト生成が可能な限り行われないようになる 244
- メソッドから無名関数への変換処理をη-expansionというのは知らなかった 251

jstatを使うとJVMのメモリ使用状況が分かる

最近頻繁に手元で起動したsbtがjava.lang.OutOfMemoryError: Metaspaceで死ぬので、メモリ使用状況を確認するコマンドを調べた。備忘録として残しておく。

の記事が参考になる。

jpsとjstatを利用する。この二つはJDKに含まれているのでインストールされていれば利用可能。

まずjpsJVMが動いているプロセスを特定する。

$ jps -v
60820 Main
55060 sbt-launch.jar -Xms1024m -Xmx1024m -XX:ReservedCodeCacheSize=128m -XX:MaxMetaspaceSize=256m
76790 Main
1067  -Xms128m -Xmx750m -XX:ReservedCodeCacheSize=240m -XX:+UseCompressedOops -Dfile.encoding=UTF-8 -XX:+UseConcMarkSweepGC -XX:SoftRefLRUPolicyMSPerMB=50 -ea -Dsun.io.useCanonCaches=false -Djava.net.preferIPv4Stack=true -Djdk.http.auth.tunneling.disabledSchemes="" -XX:+HeapDumpOnOutOfMemoryError -XX:-OmitStackTraceInFastThrow -Xverify:none -XX:ErrorFile=/Users/shibayu36/java_error_in_idea_%p.log -XX:HeapDumpPath=/Users/shibayu36/java_error_in_idea.hprof -Djb.vmOptionsFile=/Applications/IntelliJ IDEA CE.app/Contents/bin/idea.vmoptions -Didea.java.redist=jdk-bundled -Didea.home.path=/Applications/IntelliJ IDEA CE.app/Contents -Didea.executable=idea -Didea.platform.prefix=Idea -Didea.paths.selector=IdeaIC2018.3
55853 Jps -Dapplication.home=/Library/Java/JavaVirtualMachines/jdk1.8.0_162.jdk/Contents/Home -Xms8m

今見たいJVMのプロセスが55060 sbt-launch.jar -Xms1024m -Xmx1024m -XX:ReservedCodeCacheSize=128m -XX:MaxMetaspaceSize=256mだとすると、プロセスIDは55060なので次のコマンドでメモリ状況が分かる。-tはタイムスタンプをつけるオプション、-h5は5行ごとにヘッダを出すオプション、最後の1000は1秒ごとに統計情報を出力するオプション。

$ jstat -gc -t -h5 55060 1000
Timestamp        S0C    S1C    S0U    S1U      EC       EU        OC         OU       MC     MU    CCSC   CCSU   YGC     YGCT    FGC    FGCT     GCT
         1054.8 76800.0 78336.0 53909.3  0.0   192512.0 179123.1  699392.0   75597.7   106496.0 94784.9 13056.0 12218.8     20    0.296   5      0.415    0.711
         1055.8 76800.0 78336.0 53909.3  0.0   192512.0 179123.1  699392.0   75597.7   106496.0 94784.9 13056.0 12218.8     20    0.296   5      0.415    0.711
         1056.8 76800.0 78336.0 53909.3  0.0   192512.0 179123.1  699392.0   75597.7   106496.0 94784.9 13056.0 12218.8     20    0.296   5      0.415    0.711
         1057.8 76800.0 78336.0 53909.3  0.0   192512.0 179123.1  699392.0   75597.7   106496.0 94784.9 13056.0 12218.8     20    0.296   5      0.415    0.711
         1058.8 76800.0 78336.0 53909.3  0.0   192512.0 179123.1  699392.0   75597.7   106496.0 94784.9 13056.0 12218.8     20    0.296   5      0.415    0.711
Timestamp        S0C    S1C    S0U    S1U      EC       EU        OC         OU       MC     MU    CCSC   CCSU   YGC     YGCT    FGC    FGCT     GCT
         1059.9 76800.0 78336.0 53909.3  0.0   192512.0 179123.1  699392.0   75597.7   106496.0 94784.9 13056.0 12218.8     20    0.296   5      0.415    0.711
         1060.9 76800.0 78336.0 53909.3  0.0   192512.0 179123.1  699392.0   75597.7   106496.0 94784.9 13056.0 12218.8     20    0.296   5      0.415    0.711
         1061.8 76800.0 78336.0 53909.3  0.0   192512.0 179123.1  699392.0   75597.7   106496.0 94784.9 13056.0 12218.8     20    0.296   5      0.415    0.711
         1062.8 76800.0 78336.0 53909.3  0.0   192512.0 179123.1  699392.0   75597.7   106496.0 94784.9 13056.0 12218.8     20    0.296   5      0.415    0.711
         1063.9 76800.0 78336.0 53909.3  0.0   192512.0 179123.1  699392.0   75597.7   106496.0 94784.9 13056.0 12218.8     20    0.296   5      0.415    0.711

この中でMetaspaceのCapacityはMCの106496.0KB、Metaspaceで実際に利用している使用量はMUの94784.9KBとなる。この値がMaxMetaspaceSizeに指定された256MBを超えるとjava.lang.OutOfMemoryError: Metaspaceで死ぬ。


以上、簡単にMetaspaceの利用状況を知る方法でした。

epochをISO8601のフォーマットに変換するコマンド

エンジニアをしているとepoch秒をよく見るが、epoch秒だと頭でいつの時間か理解するのは難しい。ISO8601のフォーマットだとシュッと理解できる。つまり

  • epoch秒の1547018800 <- すぐに日付などが分からない
  • ISO8601の2019-01-09T16:26:40+0900 <- すぐに分かる!

epoch秒が出てきた時にシュッとISO8601のフォーマットに変換したいことがあったので調べていたのだけど、実はdateコマンドで一発だった。

Macの場合。

$ date -r 1547018800 +%Y-%m-%dT%H:%M:%S%z
2019-01-09T16:26:40+0900

Debianの場合。

$ date --date='@1547018800' +%Y-%m-%dT%H:%M:%S%z
2019-01-09T16:26:40+0900

あとはこのコマンドをepoch2dateとしてシェルスクリプトを置いておくと便利に使える。

/path/to/bin/epoch2date

#!/bin/bash
date -r $1 +%Y-%m-%dT%H:%M:%S%z
$ epoch2date 1547018800
2019-01-09T16:26:40+0900