【IntelliJ IDEA】Boolean method 'xxx' is always inverted

今日初めて見たんですが、IntelliJ IDEAでBoolean method 'xxx' is always invertedというメッセージに出会いました。

こんな感じ。メソッドの中身は超適当です。

f:id:fuji-tak:20210201185516p:plain

メッセージの通りですが、呼び出し元が全部!で結果を反転している時に出てくるみたいですね。

これでInvert methodを選ぶと、変更後のメソッド名を何にするかというダイアログが出てきました。

とりあえずNotを入れた名前にしてみて、refactorを押すと、、

f:id:fuji-tak:20210201185801p:plain

実装の中身が反転して、呼び出し元に付いてた!も全部外れてました。

f:id:fuji-tak:20210201190307p:plain

メソッドの中身が複雑でも自動でリファクタリングしてくれるのかは試せてないですが、さすがIntelliJ IDEA。気が利いてますね。

【PostgreSQL】シーケンスなどの存在確認

久しぶりに書こうとすると、どうするんだっけってド忘れしてちょこちょこ調べている気がするのでメモ。

例えばシーケンスならこう。pg_classに対してSELECTする。

select 1 from pg_class where relname = 'sequence_name' and relkind = 'S';

relkindは、それが何なのかを表す。

  • r: 通常のテーブル
  • i: インデックス
  • S: シーケンス
  • v: ビュー

詳しくはpg_classの公式ドキュメント

GraalVMってなんぞや

名前は聞くけどよくわかってないGraalVMについて、自分なりに整理してみます

公式情報を見てみる

とりあえず、まず公式情報。

GraalVM

f:id:fuji-tak:20200601001755p:plain

トップで謳われているのは

  • アプリケーションのスループットを増して、レイテンシは減るよ
  • アプリケーションを、必要なものが揃った(完パケの)ネイティブバイナリーにコンパイルするよ
  • 複数の言語やライブラリをシームレスに扱えるよ

という話ですね。この辺が大きい特徴なのかな。

f:id:fuji-tak:20200601004441p:plain

もうちょっと、Key Featuresも見てみると、さっきと大きく変わらないけど、AOTコンパイルはさっきは無かったワードなのかな。

この先の、詳細な英語ドキュメントを初心者のうちから読むパワーはなかったので、雰囲気だけ抑えて、これ以降はいろんな日本語記事を見て理解したことをまとめます。

特徴

GraalVMの2つの特徴について。

  • Polyglot
  • Native
Polyglot

多言語を混ぜて使えるよ、という話。

Java, JavaScript (Node.js), Ruby, Python, C++, R あたりが使える。

んで、JavaからJavaScriptのコードを参照、みたいなことができる。すごい。

公式のデモはこちら

Native

Key FeaturesにあったAOTコンパイル(Ahead-Of-Time, 事前コンパイル)によって、ネイティブで動作する、スタンドアローンなバイナリを作ることができます。

なおAOTコンパイル自体はJava9から導入されたもので、別にGraalVMの専売特許ではない。

いわゆる普通のコンパイルは、JITコンパイル(Just-In-Time, 実行時コンパイル)。GraalVMはJITコンパイルもできます。

バイナリのもうちょっと詳しい話は後述。

中核技術

GraalVMは、普通のJVMの発展版のようなもので、普通のJVMにできることは全部できる(はず)。

普通のJVMとは違う、GraalVMの中核技術には以下の3つが挙げられます。

  • Graal
  • Truffle
  • GraalVM Native Image
Graal

普通のJVMがこんな感じになっているのに対して

用語の説明 10
HotSpot VM
Compiler Interface
C1 (Client) C2 (Server)
• HotSpotVM
C++
← JIT Compiler
階層型コンパイラ
実行中にC1/C2両方使う

(画像はこちらの10枚目)

GraalVMはこう

用語の説明 12
HotSpot VM
Compiler Interface
C1 (Client) Graal
• Graal
–Javaで書かれたJITコンパイラ
C++
← JIT Compiler
C2の代わりにGraalを
JVMCI...

(画像はこちらの12枚目)

HotSpot VMをベースにしているのは同じで、C2コンパイラGraalに置き換わっています。

Graal ≠ GraalVM で、Graal自体は、Java製のJITコンパイラのこと。Java10以降のOpenJDKで使えるらしい。(JEP 317

Truffle

Truffleは言語実装用のフレームワーク

この人のおかげで、GraalVMは複数の言語を動かすことができる。また、独自言語の実装もできる。

GraalVM Native Image

Nativeの項でも書いたとおり、GraalVMはネイティブで動作するバイナリ(Native Image)を作ることができます。

それの何が嬉しいかというと、Native Imageは仮想マシン上(JITコンパイル)ではなくネイティブで動くので、「起動が早くなる」「JVM言語のメモリ使用量が減る」などのメリットがあります。

逆に、OSの差異を吸収してくれるなどのJITコンパイルのメリットは得られなくなる。また、リフレクションや動的プロキシを使う場合には追加の作業が必要になるようです。

まとめ

複数の言語をまたいで、それぞれのライブラリなんかの資産を活用できるっていうのはすごく便利そうなので、動かしてみたいと思いました。(小学生並みの感想)

今回ほとんど触れられなかった速度に関しては、別に速くない、むしろ遅いっていう話もあるようだけど、その辺は今後に期待みたいな感じですかね。

参考文献

tech.uzabase.com

www.slideshare.net

www.slideshare.net

nowokay.hatenablog.com

www.publickey1.jp

Javaの新JITコンパイラ、Graalを解説 - InfoQ Javaの新JITコンパイラ、Graalを解説

マージコミットのcherry pick

こういうマージコミットをcherry pickする時の話

f:id:fuji-tak:20200229171211p:plain

普通にgit cherry-pickしてみます

$ git cherry-pick -n 1adf377

怒られます。マージコミットは親が2ついるので、どちらから辿ればいいのか分からない、ということみたいです。

error: commit 1adf3776d12499e29a896d11a4d03846e7fc3c54 is a merge but no -m option was given.
fatal: cherry-pick failed

-mに見て欲しい親のハッシュ(90a3900)を指定しましたが、

$ git cherry-pick -n -m 90a3900  1adf377

やっぱり怒られました。

error: option `mainline' expects a number greater than zero
usage: git cherry-pick [<options>] <commit-ish>...
   or: git cherry-pick <subcommand>
... 

調べたところ、親番号を教えないといけないみたいなので、git rev-parseで確認します。

$ git rev-parse 1adf377^1
90a3900fa17137dc88d0a4641e386e36763666f5

$ git rev-parse 1adf377^2
6d0fda8197e66cf3c6defa7ec616e61f12b37c13

今回は親番号が1の方を見てほしかったので、mオプションで指定します。

$ git cherry-pick -n -m 1 1adf377

これでうまくいきました。


参考

親番号の調べ方の情報元 stackoverflow.com

SQLの実行計画を読めるようになる(PostgreSQL)

SQLのパフォーマンスを測定するためのプラン(実行計画)について、「俺たちは雰囲気でプランを読んでいる」部分があって良くないと思ったので、ちゃんと読めるようになるため、情報を整理する。

explain と explain analyze

まず、プランを出させる方法について。

explain
  • 予想される実行計画を表示する
explain analyze
  • 実際にSQLを発行して、その時の実行計画を表示する
  • 実際にSQLを実行するので、レコードを変更するクエリやDBに負荷がかかりそうなクエリは注意

実行計画の読み方

actual time
  • 処理時間(ミリ秒)
cost
  • cost=0.00..18.00の形式で表示される
  • シーケンシャルな読み込み1回を1.00とした場合の相対値

  • 最初の数字は初期コスト(始動コスト)

    • 最初の行が返されるまでのコスト
    • 実行する前の事前準備がなければ0.00になる
  • 後の数字はトータルコスト(総コスト)

    • 最後の行が返されるまでのコスト
rows
  • 実行結果として返ってきた行数
width
  • データのサイズ
  • パフォーマンスを見るうえでそんなに重要じゃない
loops
  • ステップの実行回数
planning time
  • 解析されたクエリから実行計画を生成し、最適化するのに要した時間
execution time
  • 実行時間

で、結局どう見たらいいのか

  • explain analyzeで実際のプランを取得
  • トータルの時間が遅かったら、原因になっている箇所を探して改善方法を考える
    • Seq Scanになっててrowsが多い
      • インデックスの追加が必要なのか?
      • WHERE節を変えて既にあるインデックスを使えるようにできないか?
    • Index Scanだけどrowsがすごく多くてactual timeも長くなってる
      • 取得しなくていいレコードまで取得していないか? (= もっと条件を絞り込めないか)
        • たくさん絞り込める条件から先に実行されるように変えられないか? (WITHとか使って)
      • JOINするレコードを減らせないか?
        • 条件を増やして、JOINする前にレコード数を絞れないか?

こんな感じ?

参考にさせてもらったページ

qiita.com

www.slideshare.net

Scalaについての基礎知識

社内で発表した時の資料を再編成しました。

Scalaについて、勉強してここまでは理解しましたという資料です。

トレイト(trait)

  • Javaでいうインターフェース
  • 抽象メンバと具象メンバのどちらも持てる
  • 複数のトレイトをミックスイン(Javaでいう継承)することができる
  • クラスを継承できる
  • トレイトの中にトレイトやクラスを定義できる
  • ミックスインは、静的な定義としてだけでなく、あとからも(インスタンス生成時に)行える。
    • つまり「こういう条件ならこのトレイトをミックスイン」みたいなことができる

タプル(tuple)

  • 型を気にしないで何でも入れられるイミュータブルなリスト、みたいな感じ
  • 戻り値として複数の値を返したり、クラスを作るまでもないような簡単なデータを表したり
  • 要素が2つならPair、3つならTripleという別名が使える
  • 要素の番号は1始まり
  • 使い方の例(イメージ)
val userA: (Int, String) = (1, "Tom")
val userB: (Int, String) = Pair(2, "John")

userA._2  // "Tom"

パターンマッチ

  • 条件分岐するんじゃなく、パターンマッチできる。これがScalaの良いところ(強いところ)の一つ
  • 型で、タプルで、正規表現で、ケースクラスで、など色んな条件が使える
  • 上から順にマッチするかチェックされて、どこかに入ればそれで終わり。
  • 使い方の例(イメージ)
式 match {
    case パターンA => { Aの時の処理 }
    case パターンB => { Bの時の処理 }
    case _ => {AでもBでもなかった時の処理}
}

ケースクラス(case class)

  • パターンマッチと相性が良い
  • Kotlinのdata classのようなもの