JavaのコンカレントGCとParallelGCThreadsについて

メモリを大量に消費するアプリケーションでFull GCが頻繁に発生し、CPUの高負荷状態、表示の遅延などの問題が発生した。

Full GCによる表示の遅延の改善にはコンカレントGCを採用することで解決した。コンカレントGCを使用するには起動オプションで-XX:+UseConcMarkSweepGCを指定する。

java -XX:+UseConcMarkSweepGC -jar /app.jar

Full GCが起きた時のCPUの高負荷状態はCPUのコアを全て使うことが原因だったので、GCを並列実行するスレッドの数を起動オプションに-XX:ParallelGCThreads=2を加えて抑えることで解決した。

java -XX:+UseConcMarkSweepGC -XX:ParallelGCThreads=2 -jar /app.jar

GCについての調査はjstatを使って行った。Full GCの発生回数、トータルの停止時間はjstatで確認できる。jpsコマンドで稼働中のプロセスIDを確認し、jstatの引数に渡すことでアプリケーションのGCの状況等が確認できる。

$ jps
28815 Jps
27493
27434 Main
jstat -gcutil -t 1 1000

参考

HttpPostでKeepAliveしているか調べる

特定のAPIに対してKeepAliveで接続をしているかどうかを確認するためにまずはtcpdumpでポート80に対する送信を監視する。

sudo tcpdump dst port 80

Flags [S]とかFlags [P.]とか出てくる。これについてはTCPDUMPの出力を見てみようを参考に読むと良い。KeepAliveが効く場合はFlags [S](SYN = コネクション確立要求)が最初に走り、その後のリクエストではFlags [P.](PUSH = バッファリングせず、即時にデータを送るようTCPに要求)のみが行われる。これでKeepAliveが効いている事が確認できる。

GUIでTCPDUMPを確認することができるWiresharkは使い方がよくわからなかったが見やすくてよかったので今後使っていきたい。

protoc-jarを使ってopenrtb.protoからOpenRtb.javaを生成する

まずは下記の手順で適当なディレクトリを作ります。

mkdir -p hoge/proto

openrtb.protoを上記で作成したディレクトリ./hoge/protoに配置し、fitsさんが紹介しているビルドスクリプトをプロジェクトルート./hogeに配置します。配置したコードは、今回のディレクトリ構成に合わせて修正したのと、最新のバージョンにしてみました。

apply plugin: 'application'
def protoDestDir = 'proto/generated'
def protoFile = 'proto/openrtb.proto'
mainClassName = 'OpenRtb'
repositories {
jcenter()
}
configurations {
protoc
}
dependencies {
protoc 'com.github.os72:protoc-jar:3.2.0'
compileOnly 'org.projectlombok:lombok:1.16.10'
compile 'com.google.protobuf:protobuf-java:3.2.0'
}
task protoc << {
mkdir(protoDestDir)
javaexec {
main = 'com.github.os72.protocjar.Protoc'
classpath = configurations.protoc
args = [ protoFile, "--java_out=${protoDestDir}" ]
}
}
compileJava {
dependsOn protoc
source protoDestDir
}
clean {
delete protoDestDir
}