Chonaso's Commentary

InternetやIT技術などについて知ったこと、試したこと、考えたことを書いていきます。

【Java8】実録 緊急JVMチューニング


発端

Amazon EC2Tomcat/Java8を運用していたとあるサービス。

サービス終了は告知済みでUUも減ってきたのでインスタンスサイズを小さくして運用費下げたいとの相談。

どのようなサイズダウンかと聞いたところ、メモリが現在31GBから9GBになります、とのこと。

この時点でEC2慣れしてる方ならピンと来るでしょう。

当時EC2のスペックなどよく知らなかった私は(ずいぶんリッチな環境で運用してたんだなぁ、最初から9GBでも十分じゃないの?てかなんで奇数?と思いつつ)とりあえず承諾。

そして当日「サイズダウンと動作確認終わりました」のお知らせを受けたのでこの件は終了、と思っていたら「一部サーバが応答しないようだ」との報告が上がってきました。

どう考えてもダウンサイズが原因でしょ、と思い色々調べてもらうと

「OutOfMemoryError出てますね😇」

まじかー、雑な運用しちまったなぁ、このサービス舐めてたわーと反省しつつ、まずはメモリ消費量の確認を依頼。

ところが調べてもらうとどうもソロバンが合いません。 メモリが枯渇するほどは使用されていませんでした。

ここで答え合わせ。 メモリサイズ(GB)として聞いていた値はECU1でした。 というわけで9GBと聞いていたメモリは本当は3.5GBでした。

さすがにこれはマズいです。

サイズ戻せば一応解決ではあるのですが、JVMチューニングで凌ぐ余地がありそうだったのでそちらで解決することにしました。


メモリ設定の確認

まず今のメモリ設定とメモリ状況をチェックします。

psコマンドでjavaコマンドラインパラメータを見れば現在のパラメータがわかります。

→ 特に指定なし

デフォルトですね(にがわら)。

$ ps auxww | grep tomcat | grep -v grep
tomcat    1348  9.0 36.9 3691336 1376316 ?     Sl   Xxx22 106:39 /usr/bin/java -Djava.util.logging.config.file=/usr/local/tomcat/tomcat8/conf/logging.properties -Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager -Djdk.tls.ephemeralDHKeySize=2048 -Djava.protocol.handler.pkgs=org.apache.catalina.webresources -Djava.library.path=/usr/local/apr/lib -Dignore.endorsed.dirs= -classpath /usr/local/tomcat/tomcat8/bin/bootstrap.jar:/usr/local/tomcat/tomcat8/bin/tomcat-juli.jar -Dcatalina.base=/usr/local/tomcat/tomcat8 -Dcatalina.home=/usr/local/tomcat/tomcat8 -Djava.io.tmpdir=/usr/local/tomcat/tomcat8/temp org.apache.catalina.startup.Bootstrap start

メモリ使用状況の確認

次にメモリ使用状況。

私はjstatコマンドが好きなのでこちらを使いました。

$ sudo jstat -gc 1348
 S0C    S1C    S0U    S1U      EC       EU        OC         OU       MC     MU    CCSC   CCSU   YGC     YGCT    FGC    FGCT     GCT
54272.0 54784.0  0.0    0.0   200704.0 196670.3  622592.0   622576.1  173312.0 141172.7 20736.0 16110.2     92    3.362 1767  2886.327 2889.688

主要な項目は以下の通りです。

  • OC Old領域の容量(キロバイト)
  • OC Old領域の使用量(キロバイト)
  • YGC Young領域GC(Scavenge GC)の回数
  • YGCT Young領域GCにかかった総時間(秒)
  • FGC フルGCの回数
  • FGCT フルGCにかかった総時間(秒)

ああこれはひどいですね...

YGC(YoungGC)が92回しかないのにFGC(FullGC)は4桁超えています。 明らかにメモリ不足です。

これでもある程度サービスが動いていたのだから大したものです。
(むしろ起動直後に即死してくれた方がよかった)

必要メモリを決める

ここから最善のメモリ設定を割り出していきます。

まずJavaアプリケーションが動作するために確保すべきメモリは以下の通りです。 (Linuxを想定しています)

  • OS
    • カーネルや最低限起動が必要なデーモンなど
    • Buffer/Cache
  • Java
    • heap領域サイズ
    • native領域サイズ(Metaspace, CompressedClassSpace, Cヒープなど)

OSについてはこの状況下ではBuffer/Cacheはほぼ見捨てていいかと思います。もしメモリが余っていれば優先度が低いなりにOSがうまく使ってくれるはず。 その他有象無象でどのくらいメモリが必要かはpsやtopコマンドなどから割り出してください。

Native領域

Javaについてはできる限りHeapにメモリを回したいのでNativeの見極めが重要です。

一番いい材料はJVMの各メモリ領域のサイズや使用量の変化履歴になりますが、そんなのがあるなら普通監視してますよね。

次点としては十分な期間起動していたJVMのメモリ状況があれば判断できると思います。

それもなければjmeter等で負荷かけまくった後のJVMメモリ状況が使えるのではないでしょうか。

今回は落とす前のjstatの結果がありますのでこれを使います。 Metaspaceは140MB程使われていました。余裕をもたせて256Mとします。

CompressedClassSpace(CCS)は16MBちょっとでした。アバウトで申し訳ないんですが64Mにしています。

CCSの必要サイズはヒープ内に存在するオブジェクトの数で決まります。

つまりアプリの作り方次第となってしまうため見極めが難しい部分ではあります。 可能であればオブジェクト統計情報を取得して設定値を検討したいところです。

またCompressedClassSpaceのサイズはデフォルトで1GBですが、このサイズはよほどオブジェクトが多くなければ消費できるサイズではないので設定することをお勧めします。 特に搭載メモリの少ない環境では必須2です。

他にもNative領域として確保される値はあるのですが、 これも適当で申し訳ないんですがCヒープはJNIを多用している・スタックは大量のスレッドを使用しているなどの状況でなければ設定自体は無視できるのではないかと思います。

Heap領域

jstat結果で確認したOld容量約608MBでは足りていないのは明らかです。

極力Old領域に振り分けることにしました。これでダメならメモリを増やします。

最終には以下の設定になりました。

-Xmx2560m -Xms2560m -XX:NewRatio=3 -XX:CompressedClassSpaceSize=64m -XX:MaxMetaspaceSize=256m

物理メモリサイズは3.5GB、スワップは極力させない、という前提です。

-Xmx2560m-Xms2560m ですが、Xmxはヒープの最大サイズ、Xmsはヒープの初期サイズです。 初期サイズを最大サイズにすることでJVM実行中の自動拡張のオーバーヘッドを無くします。

-XX:NewRatio=3 はYoung領域とOld領域の割合を1:3にする、という設定です。 つまりOld領域は1,920MBとなります。

ヒープが足りているかの判断

ベストな確認方法は負荷試験をすることです。 負荷試験は処理性能のネックだけではなくサーバリソースの限界を見極めるためにも重要な試験といえます。

短時間で見極めるにはヒープの消費トレンドを観察します。

Full GC頻度/時間

まずはFullGCの頻度を見ます。

「一定時間内に何回あったらダメ」といった絶対的な指標はありませんが回数が少ないに越したことはないです。

それに加えてFullGCに掛かった時間を見ます。1回あたりのFullGCが大きいとそれ自体がシステムへの負荷が大きく、アプリケーションの応答時間に影響してきます。

1回のFullGC時間が極端に大きければはメモリ不足にならない程度にOld領域を小さくする対応も視野に入れる必要があります。

Old使用量の増加トレンド

Full GCはOld領域が不足した時に発生します。 Old領域はFull GC以外では使用量は減少しません。

つまりYoung領域からOld領域へ移動するオブジェクトが多いかどうかでOld使用量の増加ペースが決まります。

オブジェクトがOld領域への移動するメカニズムはここでは割愛しますが、JVM設定で対応できるのはYoung領域のサイズとオブジェクトがOldに移動するGC回数(-XX:MaxTenuringThreshold)となります。

ちなみに筆者は -XX:MaxTenuringThreshold を設定したことはあまりないです。 そこまでシビアな運用をしたことがない、アップデートなどでコードが変わればトレンドが変わるなどが理由です。

メモリリークしていないか

手前味噌ですが、ここにまとまっています。 Javaアプリケーションサーバの監視 - Chonaso's Commentary

メモリリークしているかどうかはほぼコードの問題ですが、メモリサイズが大きかった場合はそれが顕在化していなかった可能性もあります。

Javaアプリはメモリ設定が変われば挙動が変わる(かもしれない)という覚悟をしながら運用していかないとならないですね。


その後

このサービスはチューニング以降何事もなくサービス終了を迎えたのでした。

めでたしめでたし(合掌)

追記

今回のケースの直接の原因はEC2サービスに対する誤解や検証不足ですが、メモリ(ヒープ)使用量やCPU使用率、レスポンスタイム、FullGC回数などの監視を適切に行なっていればサービス影響が発生する前に問題の検出ができた可能性が高く、この辺は猛省せねばならないところですね。

Apple Watchに複数のタイムゾーン時刻を表示させる(2019/11/1 追記)

先日海外出張で台湾へ行ってきました。 初めての海外ということもあり準備の勝手がわからない状況でしたが、現地でちょっと困ったのが時計でした。

現在時刻が分かる持ち込み機器はスマートフォン(数種)、iPadApple WatchMacbookと条件によって自動的に時刻が変わってしまうものばかり。そして日本と台湾の時差は1時間と体感上ほぼ違いがないというのが災いし「今表示されている時刻はどこの時刻なんだろう…」という状況に陥りました。

普段時計として主に使っているのはスマートフォンとその子機状態になるスマートウォッチ(Apple Watch)で、 基本的にはSIMが刺さっていればNITZによって現地時間に同期されるはず、なんですが設定をいじったりすると不意に日本時間に戻ってたりしてどうも不安です。

そこで思いついたのが「関係する複数のタイムゾーンを一覧できるようにすればよい」というものです。 iOSであれば時計アプリの世界時計で複数のタイムゾーンを同時表示できるので現在位置さえ分かっていれば現在時刻を確実に知ることができます。

f:id:chonaso:20190421235742j:plain
※台湾で取ったスクリーンショットなので端末は台湾時間です

でも毎回時計アプリを開くのは面倒です。 せっかくApple Watchを身に着けているのだからこれで時刻を確認したいものです。

フェイスの自作ができないApple Watch(2019/4/22時点)ですが、コンプリケーションを設定することで複数のタイムゾーンを表示することができましたのでその手順を残します。

海外に行かなくても普段UTCJSTの狭間で過ごしているITエンジニアにもおすすめです(笑)

手順

(1) iPhone上で表示させたいタイムゾーンを世界時計に登録する

iPhone側の時計アプリから「世界時計」を選択して表示させたいタイムゾーンを追加します。

f:id:chonaso:20190422000002j:plainf:id:chonaso:20190421235222p:plain

(2) Apple watchアプリのフェイス(文字盤)を追加する

iPhone側のWatchアプリを起動して「文字盤ギャラリー」を選択すると、追加したいフェイスが選べます。

f:id:chonaso:20190421235858p:plain

コンプリケーションが設定できるフェイスは限られており、今回は最低でも2つ以上コンプリケーションが設定できるフェイスが必要です。

この用途の場合は5コまでコンプリケーションが設定できるモジュラーがおすすめです。「追加」をポチるとマイウォッチに追加されます。

f:id:chonaso:20190422000614p:plain

(3) コンプリケーションの設定

「マイウォッチ」を選択すると追加されたフェイス(この場合はモジュラー)が並んでいます。

f:id:chonaso:20190422001112p:plain

追加されたモジュラーを選択すると、コンプリケーションが配置できます。

コンプリケーションの項目にある「世界時計:〇〇〇〇〇(←追加したタイムゾーン)」を選択すると、そのタイムゾーンの時刻がApple Watchのフェイス上に表示されるようになります。

f:id:chonaso:20190422001339p:plain f:id:chonaso:20190422001353p:plain

(4) UTCの表示

出来上がりはこんな感じです。もはやメインの時刻表示が不要な気もします。

f:id:chonaso:20190422001715j:plain

今回はUTCも追加してみましたが、UTCApple watchの言語設定が日本語だと「協定世界時」と表示されてしまいます。 特に小さい表示領域だと「協定…」と表示されるのでダサいです。

Apple Watch側の言語を英語にすると「UTC」になりました。(というか全部英語になります)

2019/11/1 追記

いつの間にか日本語でもwatch上で「UTC」表記になっていました。 (iPhoneアプリ上は「協定...」のまま)

f:id:chonaso:20191101131730p:plainf:id:chonaso:20191101131734j:plain

普段も業務上台湾とのやり取りがありますので当分Watchはこの状態で使おうと思います。

ちなみに海外渡航には普通の時計を持っていくのをオススメします。

参考 Can set my watch so I can see TWO time zones?

近況など(2018年末)

引き続き、昨年異動したグループ会社で働いています。 といいながら事実上別のグループ会社に派遣状態になっています。 資本関係がややこしく、出向先は自分の籍を置いている会社の孫会社、作業場所は自分の籍をおいている会社の子会社(最近になって子会社じゃなくなりましたが)という感じです。

昨年から取り組んでいるのはとあるスマホ向けゲームの開発です。 細かいプロジェクト体制の説明は割愛しますが共同開発という体で他社のプロジェクトへ参画しています。 プロジェクト推進のイニシアチブを持たないため事実上派遣社員のようなポジションです。

サーバサイドのプログラムを担当していましたが、新規ゲーム開発としてはかなり少人数で作ったな感がかなりあります。 どうにかサービスインに漕ぎ着けることができましたが、ローンチ直後は様々な問題が発生し、自分の力の及ばない外的要因が多々あったとはいえ最初の1週間は生きた心地がせず、久々にB2Cサービス運用で内臓をキリキリバクバクいわせる日々でした。 自分としてはなんとか早期に諸問題を収束させることはできたと思っていますが、この間プレイヤーの皆さんにもかなりご迷惑をお掛けしてしまった部分も多々あり反省しきりでした。

よく考えてみると自分のキャリアの中で他社のプロジェクトを他社内で開発するという経験は初めてでした。 新卒時はSIerでしたがすべて自社内での開発作業でしたし、その後は多くの仕様決定やほとんどの技術要件については強い影響力を持つ立場でやってきたこともあり、あまりの勝手の違いに戸惑い納得のいかない日々を過ごしました。 特にプロジェクトマネジメントに関してはフラストレーションが溜まるものではありましたが、アンチパターンの数々を身をもって知ることが出来たともいえます。 また、これまでそういう立場で一緒に仕事をしていた人たちが何を感じてきたか、ということも少し理解できた気がします。

逆にサービス運営については知らないことばかりで、今所属している会社の社長からは配属直後に「スマホゲームはリリースした時点でスタートライン、リリース以降どれだけ熱をもって盛り上げていくかが重要」的な教えをいただきましたが、いざローンチしてみるとその施策は私の知らないことばかりでした。 今回ローンチしたゲームは手前味噌ながら非常に面白いゲームだと思っていますが、ただ面白いだけでは広がらない未プレイの人に届かない、続けられるだけの要素がなければ続けてもらえない、そして基本プレイ無料でも誰かに課金してもらわないと運営が成り立たないわけで、これを決して大きくない組織で他のビッグタイトルと渡り合っていかないとならないというハードな運営が続いていきます。

前職でもそれまで知る機会もなかった営業の大変さを知ることができましたが、「こんな機能要らないだろ」と思いながら作っていたものがゲームに不可欠な要素あるいは非常に意義深いものであったことをローンチ後になって初めて気付かされることもありました。 これまでも事業会社に身を置いていた者としてある程度俯瞰できていると思っていた「事業」というものに対して自分の見識の狭さ・浅はかさを改めて痛感させられています。


この体制下での作業については1~2月には撤収、徐々に引き継ぎモードに入りつつあります。 その後はようやく自社での作業となり1年半ぶりのプロマネ業に戻る見込みです。

自分の本籍である出向元の会社はその親会社の植民地化が進み、今年は古くからの知り合い(特に管理職)の多くが会社を去っていきました。 私が戻れるところももはや無さそうです。2019年は背水の陣と思って取り組んでいきたいと思います。

JJUG CCC 2018 Fallに行ってきました #jjug_ccc

ここのところ、仕事の大半がPHPなのでJavaの話題に触れたい&刺激をもらいにJJUG CCC 2018 Fallに足を運びました。 所用があったので後半からでしたが非常に興味深い内容ばかりでした。


Deep dive into instanceof #ccc_a5

Deep dive into instanceof

広告配信システムを担当している登壇者が指摘された 「ハイパフォーマンスが求められる環境においてinstanceofは悪手、そもそもdowncastはoop的に設計が間違っているケースが多いのでは」 というレビューコメントを端緒にJavaVMのコードを追ってみた、という内容で、 単なるループで回している(辿る)わけではなく、実際にはinstanceofに耐えうるKlassのクラス設計(紛らわしい)や継承/実装の違いやツリーの深さなどでアルゴリズムを変えるなどのそれなりの考慮がなされているということでした。

Javaとは縁遠いプログラムカウンタやスタックポインタなどを知らないと即死するような内容でしたが、 デバッガを使っているとたまによく見るKlassが出てきたり、 instanceofのパフォーマンス向上についてはそれなりの紆余曲折があった*1のだな、ということを知りました。

思えば学生時代はC言語のライブラリのソースコードを読んでいたのにJVMのソースとか読む気が起きたことがなかったなぁ。 (PHPは必要にかられて読むことがある…)

ただ、あの内容だと場合によってはレビューコメント論破できる(instanceofでもいい)ケースもあるのでは?という気もしなくない(笑)


オイラ大地の18年拡張し続けているECサイトをSpring Bootとk8s on Azureでマイクロサービス化する事例 #ccc_a6

オイラ大地の18年拡張し続けているECサイトをSpring Bootとk8s on Azureでマイクロサービス化する事例

  • 品質の維持
  • ローンチスピード
  • スケーラビリティ

この3つを満たすシステムを開発・保守していくにはという問題に対し、マイクロサービスアーキテクチャでアプローチしていくことを決め、 kubernetes on Azureに辿り着いて絶賛マイグレーション中です、という内容。

自分も以前とある死にかけの会社にブチこまれて上記3課題を解決するよう命ぜられ、マルチクラウド移行やマイクロサービス(当時はこの呼び方はまだなかった)を絡めたシステム移行を手がけたので色々思うところがありました。 そしてECでJavaでモノリシックでOracleで…とこれまた構成も似てて「歴史のあるJavaシステムってなんだか知らないけどOracle多いよね!」と色々と思い出しました。

マルチクラウドあるあるとしては「サービスがクラウド越えするのでレスポンスが悪化する(下手すりゃ複数回往復する)」「これまで磨き上げたCD(継続的デリバリ)が使えない」など、マイクロサービス化あるあるとしては「トランザクションが越えられない」「今まではDB上でjoinしてた」などあり、これらの問題は、個々に少しづつ解決・移行していっているとのこと。

マイクロサービス化のフレームワークとしてのSpring bootは割愛だったのでもはやJavaとは直接関係ないセッションになっていましたが、Javaを使う会社は硬い感じがするので一度動いてるシステムに手をいれるということに難色を示す非エンジニアリング部署(ともすればシステム担当も)との云々も多いでしょうから皆感じ入るところが多かったのではないでしょうか。


GCを発生させないJVMとコーディングスタイル #ccc_a7

GCを発生させないJVMとコーディングスタイル

タイトルからすると「こういう処理はこういうコードを書けばGCは起こらない!」的な内容に見えますが、このセッションではJVM(GC)の種類やコンパイラオプションによってどのように変わるかという内容でした。

昔とあるJavaの勉強会で何度かJavaのメモリ設定やGCについての内容を発表したことがありますが、その辺とはレベルが全く異なり2つ前のセッション同様PCやSP、ニーモニックが普通に出てくる内容でした。 また、デモが多かったのですがJVMオプションを手打ちでバシバシ入れていく姿はさすがJVM開発者ですね...

恥ずかしながらTLAB(Thread-Local Allocation Buffer)やEscape Analysis(EA)は初めて知りました。 説明は非常にわかりやすかったです。 ただ、正直この動きを読みながらチューニングしたりできるかと言われると・・・今度Javaシステムのお世話をした時に妙なGC挙動があったとき思い出せればいいなと思います。

つまるところGC抑止の唯一無二の策というものは存在せずJVMの種類やインライン状況によってはGCが発生したりしなかったりするもので、コンパイラの動きを予測してトリッキーなコードを書くのではなく「まずは見やすいコードを」とのことでした。 おそらく見やすい素直なコードが日々進化していくJVM進化の恩恵を一番受けやすいということなのでしょう。


※発表スライドが公開されたら更新します

近況など(2017年末)

今年夏ごろに異動しましてグループ会社で働いています。 転職後、配属部署→グループ会社に出向→帰任、からの出向なので新卒入社を会社から通算して感覚的には5社目です。

それまでは新規事業のシステム担当でした。 ロクに要件も無い中から開発1年でローンチ、その後も膨大な数のシステムを作り続け、膨大な数の障害連絡をもらいました。 結果5年半携わりましたが自分の中では最長記録です。

今回は初めて自分で希望を出しての異動です。 元々B2C志望だったのにいつの間にかどっぷり基幹/業務システムに漬かってしまっていて、いいかげん軌道修正したいという思いがありました。 あと体調面。はっきり言ってしまえば電通顔負けのブラック部門だったのでこの最初の3~4年で心身共にだいぶやられてしまっています。 最近は親会社の強い圧力でオフホワイトくらいにはなっていると思います。

そもそもローンチさせたらすぐ抜けられると思っていたのですが、先に周りが脱落していくという状況だったため自分の中でいいタイミングがつかめませんでした。 そこで「この事業が黒字になったら辞めよう」と決めていました。自分の中のケジメみたいなものです。 そしてようやく昨年度に黒字がほぼ決定的になったので異動の希望を出しました。 自分が携わっている事業がブレイクイーブンに到達したのは初めてですが、思ったほど感動はなかったです。 (その前の事業は債務超過状態からの参画でしたが黒字転換の1か月前に帰任でした)

異動については強制力のある制度を使ったので異動自体は上手く行きました。 思えばこれまで社内やグループ会社からのオファーは私に降りてくる前に全部潰されてるんですよね。 社内ハックとしてこの制度をうまく使えばよかったなとかなり後悔しています。

異動の際、上司に「ここで得たものはあるのか」と聞かれ、答えに詰まってしまいました。 技術的な部分は誰かから教わったものはほぼ無く、やっていく中で自ら勉強して身に付けたものばかり。 強いて挙げれば業務システムを作る上での経験則でしょうか。 今思い返すと細かいレベルでは色々ある気がします。

というよりも、社会人になって以来何か直接的に教わったことはほとんど無く、ただひたすら試行錯誤と実践の場を与えてもらっただけだなぁ、と改めて感じました。 もちろんそれだけでも恵まれているとは思います。

で、今はとあるスマホ向けゲームの会社でゴリゴリPHPを書いています。 同年代は少ないですが、周りはオタクばかりで楽しいです。

プロジェクト管理や定例MTGなどは無く、1日中コーディングしてるなんて新卒の時以来かもしれません。 PHP自体はPHP4の時代に仕事でちょろっと書いていたくらいなので、ほぼゼロから始めたようなものですがなんとかやれています。 さすがに数か月PHPを触っていると思うことも色々あるのでそのうちエントリにしたためたいと考えています。

JJUG CCC 2017 Spring #jjug_ccc に行ってきました

ここ1年、業務へのモチベーションが全く上がらず、それにつられて業務外での情報収集も怠っておりました。

環境も変わる兆しが見えてきたところで少しはモチベーション上げていかないとなぁ、ということで刺激を求めてJJUG CCC 2017 Springへ参加してきましたので感想などを。

スライド関連はまだ出そろっていないようなので、随時補完していきます。


#ccc_c4 Unified JVM Logging: Java 9 から変わる JVM ログ

Java 9にはJVMログ出力の新オプションである-Xlogオプションが追加されるという話です。

JVMログ、といっても個人的にはGCのログくらいしか扱ったことがないですが、 人に説明するにも難儀するあのGCログが読みやすくなるようなら良さそうですね。 過去記事でもGCログをパースしてメモリリークの検出する、みたいなことを書いてますが、 「とはいえGC設定変えるだけで書式変わるしパーサ書くのつらいんですが」みたいなことを言われても「仕方ない」の一言で済ませてましたし。

-Xlog[:[what][:[output][:[decorators][:output-options]]]]

  • what:出力項目
    • tag:ログ種別(カテゴリ)
    • loglevel:debug,infoなど
  • output:出力先
  • decorator:ログ行頭に出力する情報(日付など)
  • output-options:ローテーション設定など

どのタグを出力するか、という設定は論理式っぽいもので指定するのですが、 -Xlogは複数書けるので種類ごとにファイルを分けちゃった方がわかりやすいんじゃないかなと思った次第。

あと、jcmdでログ設定の変更や強制ログローテート可能、ログ内でpauseを含む行に記載されている秒数はいわゆるstop the world状態とのこと。


#ccc_g5 Introduction of Project Jigsaw

Java 9に組み込まれる(かどうか不明になってしまった)注目機能。 仕様検討自体はずいぶん前からあったわけですが、Java 9になっていよいよ組み込まれるということになっています。

Javaでは関連するクラスファイルをJARファイルにまとめることである機能毎のライブラリとして管理していますが、 JARファイルの連鎖的な依存関係、パッケージ内クラスのスコープの制約(どうしてもpublicにせざるを得ない問題)が運用上の課題です。

このソリューションとしてModuleという新概念が作られました。

  • module-info.javaにrequires(依存パッケージ)とexports(公開するパッケージ)を記述
  • jarコマンドでmodule化(suffixは.jar)
  • Javaランタイムも機能グループ毎にモジュール化される
    • jlinkコマンドで任意のモジュールのみを含めたオリジナルJREが作れるようになる
    • 既存のスコープにも影響が出てくる。リフレクション系など
  • 既存のJARファイルは一定ルールに乗っ取って自動的にmoduleのように扱われる

逆にmoduleをJARとして扱われた場合にはおそらくスコープ等は関係ないことになってしまいますね...

ところがこのJSR376 JigsawはJavaコミュニティの投票でNGとなってしまいました。 (Jigsawが含まれるJSR379 Java9がOKにもかかわらず、です)

ざざっと話を聞いた限りでは拙速感は否めず、NGを出されたのも理解できます。 (元々の問題の全てを解決できてない部分もあるような…)

あと、最新版では以前あったオプションや機能が変わったりオミットされていたりするようで、 数か月前以上の記事等はあまりアテにならない部分が色々出てきているようです。

そもそも今書いているこの内容すらウソの可能性もありますが…


#ccc_c6 劇的!データベース・ビフォーアフター 時代はディスクからインメモリーへ――

10年くらい前にOpen terracottaが話題になったなぁ、というのをふと思い出しました。 (あの頃は多くの人が「アレ面白そうだよね!」で終わっていた気がします)

RDBMSディスる体でのプレゼンでしたが、インメモリデータグリッドの効果的な適用シーンの紹介という内容です。 NoSQLに置き換えても文脈がかわらない内容なので、NoSQLとの比較が欲しかったと個人的には感じました。 (この内容でもNoSQLより速そうだというのはわかるんですが)

  • 複数VM間で同一Mapオブジェクトを共有するイメージ
  • メモリが主、RDBMSがバックアップ(非同期で書き出す)
  • データは複数台で冗長して保持、1つが落ちても自動的にPrimaryが移行・他にバックアップ作成
  • キャッシュミスしたものはDBから取り出すことで大容量データに対応
  • 高速処理が可能、スケールアウトが可能
  • Spark+HDFSにおいてspark workが多いときのメモリ利用効率向上
    • ダブったデータが集約される
  • SQLライクなクエリはRDBより遅い

SparkとHDFSの間に挟めるというのは面白い活用だと思いました。 他のクラスタを組むJavaプロダクトへの活用もありそうですね。

成功事例を聞くと明日からコレ使うわwwwみたいな感じになりがちですが 遍く全てのアプリがインメモリへマイグレートしていくことはなく、 現実的には効果的な部分に適宜適用していく形になるのでしょう。

細かいところですと、開発においてはVM立ち上げた直後のデータはどうしているのか、 プレゼン中では表面だけ説明したトランザクションの中間処理はどのように解決したのか、 この辺りが気になるところです。