2017-05-03

Java: CMS GC is endless

メモリが空いているのに CMS GC が掛かり続けることがある。といっても Full GC ではないので、CPU と GC ログを食うだけで運用上の問題はないのだが、はっきりした理由が分からないと安全だと言い切ることもできない。私もこれまでに何度か調べてきたが、ずっと原因が分からずにいた。

今は少しググれば有用な情報がたくさん得られる。いい時代になったもんだ。これらの情報が 2010 年以前にあれば、私もどれだけ楽ができたか知れない。しかし、これらの情報は今回の私の問題を解決しない。例えば nekop 氏によると、

CMSが開始されるトリガーは二つある。ひとつはOld領域の利用率がCMSInitiatingOccupancyFractionに到達した場合。もうひとつは今CMS走らせないと先にヒープ埋まっちゃうよね、という統計判断を元にしたトリガー。

CMSInitiatingOccupancyFraction の初期値は 92%。しかし繰り返すが、メモリは十分に空いている。ヒープを 50% しか使用していないのに、CMS GC が掛かり続けることの説明にはならない。じゃあもう 1 つの「統計判断」とは何なのか。

後者の統計については細かい話になるので省略する。知りたい人はソース嫁。

orz。うん、まあ、ね。私もかれこれ 5 年以上この現象を見てきているので、そろそろ億劫がらずにコードを読んでみる時期なのかも知れないな。

現場で動いているのは Java 6 なのだが、ソースコードを見つけられなかったので Java 7 を見てみる。しかしコードを見たからって、そんな簡単に解決するんだったら世話ないっての。

・・・1 時間後。

解決しちゃった。 :-D

bool CMSCollector::shouldConcurrentCollect() {

  // ...snip...

  // Otherwise, we start a collection cycle if either the perm gen or
  // old gen want a collection cycle started. Each may use
  // an appropriate criterion for making this decision.
  // XXX We need to make sure that the gen expansion
  // criterion dovetails well with this. XXX NEED TO FIX THIS
  if (_cmsGen->should_concurrent_collect()) {
    if (Verbose && PrintGCDetails) {
      gclog_or_tty->print_cr("CMS old gen initiated");
    }
    return true;
  }

  // ...snip...

  if (CMSClassUnloadingEnabled && _permGen->should_concurrent_collect()) {
    bool res = update_should_unload_classes();
    if (res) {
      if (Verbose && PrintGCDetails) {
        gclog_or_tty->print_cr("CMS perm gen initiated");
      }
      return true;
    }
  }
  return false;
}

重要なのは後半の部分。つまり、通常のヒープ領域だけでなく、Permanent 領域も CMS のトリガーになる ということ。この閾値は CMSInitiatingPermOccupancyFraction で、やはり初期値は 92%。

これで全てに納得がいった。これはつまり、Permanent 領域の使用量を把握して MaxPermSize を最適化しているほど、この現象に遭いやすくなるということだ。そういう場合、この値は限りなく 100% に近づけるのが正しい。(でなければ MaxPermSize を増やす)

-XX:CMSInitiatingPermOccupancyFraction=99

CMS でも、どうせ偶に concurrent mode failure や promotion failed 由来の Full GC は起こる(このとき Permanent 領域も GC される)し、Permanent 領域の変動がよほど大きいアプリケーションでもなければ、これで良いと思う。

しかしこの Permanent 領域の CMS トリガーは、もっと有名になって良いと思う。少なくとも、CMSInitiatingOccupancyFraction を出す際は、合わせて CMSInitiatingPermOccupancyFraction についても触れるべき。

2017-05-01

Animes in the 1st quarter of 2017

アニメは IT エンジニアの必須科目です。 ということで簡単なレビューを。

まさか 1 年も続くとは思わなかったよ。必殺技の演出とか、紅緒たんが可愛いとか、良い面は沢山あれど、やっぱり 1 年は間延びする。2 クールくらいでギュッと圧縮して欲しかった。

最初はイマイチだったが、コーチが出てきてから良くなった。でもまだ足りない。もっと勝負に対する真摯な姿勢を描写して欲しい。「勝敗は試合の前に決まっている」というのは、何事にも通じる良い言葉。

前期より視聴。本当に True End 版が来たっぽいが、話は訳の分からない方向に。これは Bad End 版の方が面白いですわ。女子キャラが魅力的な作品で女子キャラをろくに出さないとか、ちょっと分からないですね。

ヴィーネ良し、サターニャはなお良し。ラフィもまあ許せる。たがガヴ、てめーは駄目だ。作品のヒロインが作品を一番面白くなくしている。正直、中の人が合ってないように思う。逆に、サターニャの大空直美は覚えた。

前期に続き、作品は面白いと思う。しかし、OP からして、作画はどうしてこうなった。こうなる前に誰か止められなかったのか。これは間違いなくスタジオディーンの汚点となった。

この制作会社はいつも初話で芸術レベルの絵を見せてくれるが、いつもそれが続かないのは何故なのか。今回は話も単調でつまらない。結局、何ひとつ謎が解明されてないような。

知らずに見たら京アニだったが、なぜこれをアニメ化しようと思ったのだろう。まあ、カンナたんが可愛かったので見た甲斐はあった。あとエンジニア的には、Python のソースコードとか。

ヒロインが「残虐姫」という割には、案外チョロくてテンプレートだったのはアレだが、何だかんだ可愛かったので良し。次回に続くのは構わないが、もう少し切りの良いところで区切ろうよ。

前作は未視聴。絵はちょっとアレだが、そこは科学アドベンチャーシリーズ、話は普通に面白い。これなら面倒くさがらずに前作も見ておけば良かった。

実は 0.5 話で切ったのだが、どうしてこうなった。見返してみても理由が分からない。当事者も「正直なにが起きているのか困惑」したらしいが、ほんこれ。納得はいかないがこうなった以上、必須科目であるのは間違いない。

かつて上京していた身としては、アキバの現状が垣間見れたのは興味深い。東京に住んでいたらより楽しめたと思う。まあ作品が面白いかは別として。

OP を見れば話が読めて、そこから意外性もないので、見ていて退屈。それより巻末の「ちぇいん黒にくる!!」が本命だった。あのキャラを大塚明夫が演じていることだけでも価値がある。

見る前は全く期待していなかったが、人情味あふれた心地よい勧善懲悪もの。結局、今期はこれが一番面白かった。ぜひ続きを作って欲しい。

ノイタミナ枠でこの手の作品をやるとは意外。原作者の漫画は好きな方で、本作は先っぽしか読んでなかったので普通に楽しめた。ただ、題名にそぐわない綺麗な終わり方が少し物足りない。

2017-02-09

Animes in the 4th quarter of 2016

アニメは IT エンジニアの必須科目です。 ということで簡単なレビューを。

シリーズ通しての視聴。4 期以降、マンネリ感が強くなってきた。毎回、新規の視聴者に向けて作品解説のくだりを繰り返すのも、飽きを加速させている要因のような気がする。

前期は色々と新鮮だったが、本作はそこからの進歩が見られず、むしろ退化している。OP・ED はイケてないし、話も取って付けた感が半端ない。特にラスボスの改心っぷりには笑える。

例によって不幸を背負わされる魔法少女たち。もういい加減、魔法少女たちを「まどマギ」の呪いから解放してやっても良いのでは。独特なキャラデザや魔法少女(♂)など、新鮮味があっただけに悔やまれる。

OP を始め、全体的に良くできていると思う。ただヒロインのキャラが弱い。そんな中、裕美音が非常に良いキャラなので、それと絡めてもっと面白くできた気がする。

本系は「!!!」のみ視聴。少し恋愛に偏り過ぎな気もするが、キャラが一新しても安定しているなと感じた。と思ったら、実は原作ではこっちの方が初出だということ。なるほど。

前作は視聴したはずだが記憶の彼方。キャラを一新する理由はよく分からないが、今回は方向性がロリっ娘からお姉さん系になった気がする。とりま、次回があれば見るつもり。

安定の 5bp シリーズ。個人的にも今回の題材はなかなか興味深かった。ていうかこれで終わり? ほんとに? 何か重要な伏線が残っている気がするのだが。てか結局、梨々花って何物だったん?

何度見ても OP が「咲」を連想させる件。であればもう少しキャラごとの必殺技を前面に推しても良かった。割と本気で「咲」の卓球バージョンはアリだと思う。

前期より視聴。これから鏡花たんがバンバン出るのかと期待していたら、おもむろに野郎の昔話が始まった件。この瞬間、私にとっての本作はオワタ。\(^o^)/

前期は未視聴だが、何とも不思議なヒロインの存在感。最初「何だこの演技は」と思ったが、終わってみればあの演技があってこそのこの作品、と思えてしまう不思議。

ネット検索のこのご時世、紙の辞書編纂という題材は逆に新鮮。と同時に、やっぱり辞書の編纂人は変態だということも良く分かった。作品としては決して万人向けではない。

2016-10-31

Animes in the 3rd quarter of 2016

アニメは IT エンジニアの必須科目です。 ということで簡単なレビューを。

またタイムリープかと思ったのも束の間、序盤は神展開。その反動か中盤は糞展開。終盤に持ち直す感じ。あと意図的だとは思うが、主人公がやたらイラッとくる。あの軽薄さで引きニート設定は無理があるかと。

各キャラの掘り下げが上手いのが Key 作品の特徴なのだろうか。特に委員長のくだりはずるい。しかし終わらせ方はあれで良かったのか疑問。ひょっとして次は True End バージョンが来る?

今期の一番はこれ。主人公の知略はもちろんのこと、ヒロインとの厚い信頼関係が見ていてとても心地よい。早く続きを作って欲しいところだが、種田梨沙が休業ってそんなー。

一見、NHK 教育でやってそうな雰囲気の作品。いわゆる悪役っぽいのも出てくるが、最後はきっちり拾い上げるし、本当に NHK でやってもおかしくない内容だと思う。

初話を見てかなり強引だなと思いつつも、結局最後まで見てしまった。ばらかもんのスピンオフだと気付いたのは途中から。最初はパクリかと思った。でもやはり設定に無理があると思う。

今期コメディ枠の一番。とにかく、ヒロインと小澤亜李の親和性に尽きる。この手のキャラを演らせたら、彼女の右に出る者は居ない。個人的にはコレットさんもお気に入り。

今度はゲーム制作業界の話か、と思ったら、業界の具体的な描写はほぼ無し。もっと SHIROBAKO みたいなのを期待した。ただし作品自体は絵調や雰囲気など好みで、単に想像と違ったというだけ。

序盤こそ良感触だったが、中盤からどんどん安っぽくなっていく。特に最終話が酷かった。これで「次期もあるよ」とか言われても、面白くない予感しかしない。

この手の女子向けは基本スルーだが、志倉千代丸が企画ということで視聴。結果、他の女子向け作品と余り大差なかった。A&R という職種も謎。ただ、つばさちゃんはいい娘だと思います。

わざわざ新キャラにする意味が分からなかったが、結果から言えば 1st よりも楽しめたので、これで良かったのかも。しかし CG をそのままアニメに使うのは手抜き。その辺はアイマスを見習うべき。

始まったと思ったら終わっていた。何を言っているか(ry。ていうか何故 4 話だけやろうと思ったのか。

最初は渋めでいい感じに始まるも、それ以降が盛り上がらなかった。復讐というには主人公の冷徹さが足りず、いろいろと中途半端だったように思う。

言い方は悪いのだろうが、夏目友人帳の明るめバージョン。他に言葉が見つからない。安倍晴明とか出てくるし、原作者はきっと女性とみた。

前期より視聴。ちょうどこの辺まで原作を読んでたっぽい。これから未知の領域へ、と思ったところで終わった。ちょっと短くないですかね。あとやっぱり絵が原作の雰囲気に合わないと思う。

歌と三角関係とバトル、というマクロスの三大要素はきっちり入っている。しかしフロンティアの壁は厚かった。超えられたのは楽曲だけだと思う。何だかんだでやっぱりシェリルは偉大。

シリーズ通して視聴。舞台が変わっても、バカやってるときは面白いがバトルになるとつまらなくなるのは変わらず。バカやってる間は文句なく面白いので、ずっとそうしてれば良いのに。

主人公がなかなか本気出さないので全然盛り上がらない。ようやく本気出したと思ったら一番いい所で終了。って何これ。流石にこれは評価できない。ノイタミナ枠でこんなひどいのは初めて見た。

最近は名前ばかりのガンダムが多いが、これは紛れもなくガンダム。冨野作と聞いても疑わないレベル。老人は見ておくべき。逆に、若者がこれをどれほど面白いと思えるのか興味がある。

2016-10-27

Windows batch: Multi-level variable expansion

この間 getopt.cmd を書いていて思った。変数展開した結果を変数展開するにはどうすればいいんだろう?、と。言葉にすると難しいが、要は C 言語でいうところの、ポインターのポインターから元データを参照する感じ。

call を使うのがいいようだ。call には変数展開後の文字列が引数として渡るので、どんなコマンドにも応用できる。call にこんな使い方があったとは。

test.bat:

@echo off
set hoge=HOGE
set r_hoge=hoge
set rr_hoge=r_hoge
echo %hoge%
call echo %%%r_hoge%%%               & rem run 'echo %hoge%'
call call echo %%%%%%%rr_hoge%%%%%%% & rem run 'call echo %%%r_hoge%%%'
>test.bat
HOGE
HOGE
HOGE

Windows バッチはこういう妙なところで懐が深かったりする。やろうと思えば大抵のことは(頑張れば)できる。でもどんな良い面があっても、圧倒的マイナス面で ks 扱いされる Windows バッチさん。

2016-10-23

Windows batch: Getopt

Windows バッチが ks なことは今さら言うまでもないが、最もお手軽な手段であることも事実。特にユーザーに配布して実行させたい場合、環境の差異を気にしないくて良いのは何にも勝る利点だ。同様の意味で WSH も素晴らしいが、結果が同じならよりシンプルな方を選びたい。

という訳で私はよくバッチも書くが、ちょっと凝ったバッチを書こうとしたとき、オプション処理にはいつも悩まされる。きちんとやろうとすると面倒だし、どうせならこの手の処理は共通化したい。誰か getopt みたいなやつ作ってねーのかよ、と偶にググってみても、これといったものが見つかった試しがない。

まあ、もしバッチでできたらとっくに誰か作ってるよねー、と今までは諦めていたのだが、今回ふと思って試してみた。

test.bat:

@echo off
setlocal
set opt=hoge
set opt_%opt%=HOGE
echo opt_hoge=%opt_hoge%
>test.bat
opt_hoge=HOGE

え!? set の左辺で変数展開できちゃうの?

そうか、set もコマンドだから、引数中の変数は展開されてから set に渡るのか。ていうか、これ使えば getopt できるんじゃね?

getopt.cmd:

@echo off

if not "%~1"=="/?" goto :main
echo.Usage:
echo.  call %~nx0 [/OPTION[:VALUE]]...
echo.
echo.Description:
echo.  Parse options and define 'OPT_^<OPTION^>' variables, and set 'OPTIND' as
echo.  the number of processed arguments.
echo.
echo.Exsample:
echo.  When a batch file is invoked with arguments,
echo.
echo.    ^>example.bat /foo /bar:BAR /baz:"B A Z" arg1 arg2 ...
echo.
echo.  In the batch file, a typical usage is:
echo.
echo.    call %~nx0 %%*
echo.    for /L %%%%i in (1,1,%%OPTIND%%) do shift /1
echo.
echo.  Then a boolean option '/foo' can be tested as below.
echo.
echo.    if defined OPT_FOO ^(
echo.      echo /foo was given
echo.    ^) else ^(
echo.      echo /foo was not given
echo.    ^)
echo.
echo.  Other options have a value can be used as regular variable.
echo.
echo.    echo bar=%%OPT_BAR%%
echo.    echo baz=%%OPT_BAZ%%
echo.
echo.  Remaining arguments are referred through batch parameter.
echo.
echo.    echo args=%%1 %%2 %%3 %%4 %%5 %%6 %%7 %%8 %%9
echo.
echo.  Note that '%%*' batch parameter is never updated by 'shift'.
exit /b 1

:main
set OPTIND=0

:_loop_args
  set _getopt_arg=%1
  if defined _getopt_arg (
    call :parse_arg %_getopt_arg%
    if not errorlevel 1 (
      shift /1
      set /a OPTIND+=1
      goto :_loop_args
    )
  )
set _getopt_arg=
set _getopt_opt=
set _getopt_value=
set _getopt_bool=
exit /b 0

:parse_arg
set _getopt_opt=
set _getopt_value=%~1
set _getopt_bool=1
if not "%_getopt_value:~0,1%"=="/" goto :_parse_arg_ret
set _getopt_value=%_getopt_value:~1%
:_loop_arg_chars
  if not defined _getopt_value goto :_parse_arg_ret
  if "%_getopt_value:~0,1%"==":" (
    set _getopt_bool=
    set _getopt_value=%_getopt_value:~1%
    goto :_parse_arg_ret
  ) else (
    set _getopt_opt=%_getopt_opt%%_getopt_value:~0,1%
    set _getopt_value=%_getopt_value:~1%
  )
  goto :_loop_arg_chars
:_parse_arg_ret
if not defined _getopt_opt exit /b 1
if defined _getopt_bool (
  call :set_opt %_getopt_opt% %_getopt_bool%
) else (
  call :set_opt %_getopt_opt% %_getopt_value%
)
exit /b 0

:set_opt
set OPT_%1=%~2
exit /b 0

できちゃった :-D。使い方は次の通り。

test_getopt.bat:

@echo off
setlocal

call getopt.cmd %*
for /L %%i in (1,1,%optind%) do shift /1

if defined opt_hoge echo /hoge was given
if not defined opt_hage echo /hage was not given
echo /piyo=%opt_piyo%
echo /fuga=%opt_fuga%
echo /boke=%opt_boke%
echo %1 %2 %3 %4 %5 %6 %7 %8 %9
>test_getopt.bat /hoge /piyo:PIYO /fuga:"FU GA" /boke: arg1 arg2 ...
/hoge was given
/hage was not given
/piyo=PIYO
/fuga=FU GA
/boke=
arg1 arg2 ...

まだ改良の余地はあると思うが、私が使うには当面これで十分。

ところで今回の件で、Windows バッチは変数名に記号(どころか空白も!)を使えることを知ったが、ならば getopt.cmd に /? を渡せば変数 opt_? を定義してくれそうに思う。しかしそれは叶わない。

>call getopt.cmd /?
バッチ プログラムを別のバッチ プログラムから呼び出します。

CALL [ドライブ:][パス]ファイル名 [バッチパラメーター]

  バッチパラメーター   バッチ プログラムで必要なコマンド ライン情報を指定します。

コマンド拡張機能を有効にすると、CALL は次のように変更されます:

<...snip...>

call が /? を奪い取る模様。やっぱ Windows バッチって ks だわ。

2016-10-11

ADODB.Stream: Read write-locked file

あるシステムのログ集計を、Excel マクロでやろうとしたときのこと。

ログは UTF-8 で書かれており、ググれば ADODB.Stream を使えば良いことは直ぐに分かる。ほどなくマクロは完成し、本番投入の直前、その問題は発覚した。

ADODB.Stream.LoadFromFile は、書き込みロックが掛かったファイルを読み込めない!

それはつまり、システムが開いている当日分のログを集計できないことを意味する。しかし、今回の要件としてそれは受け入れられない。何てこった。そんなこと Google 先生も教えてくれなかったよ。

Sub Test1()
    With CreateObject("ADODB.Stream")
        .Type = 2   ' 2=adTypeText
        .Charset = "UTF-8"
        .Open
        .LoadFromFile "WriteLocked.txt"
        ' ReadText...
        .Close
    End With
End Sub

ならば、アクセスモード(Stream.Mode)を読み取り専用(adModeRead)にすれば開けるはず・・・、

Sub Test2()
    With CreateObject("ADODB.Stream")
        .Mode = 1   ' 1=adModeRead
        .Type = 2   ' 2=adTypeText
        .Charset = "UTF-8"
        .Open
        .LoadFromFile "WriteLocked.txt"
        ' ReadText...
        .Close
    End With
End Sub

どういうことなの。

恐らく、アクセスモードは Stream に対してのものであり、Stream が読み取り専用となったために Stream への書き込みメソッドである LoadFromFile がブロックされたのだと思われる。そうすると LoadFromFile に対してアクセスモードを指定する術がない以上、この方向での解決策は絶望的に思える。

ではファイルの読み込みは別の手段で行い、それを Stream に食わせたらどうか?

じゃそれ FileSystemObject で! と思ったら、FileSystemObject はバイナリファイルを読み込めないときた。ダメ元で無理やり読み込ませてみたら、化け化けになった。泣きたい。

結局、最も基本的な方法で読み込ませることで上手くいった。

Sub Test3()
    Dim fd As Long, _
        buf() As Byte
    fd = FreeFile
    Open "WriteLocked.txt" For Binary As #fd
    ReDim buf(LOF(fd))
    Get #fd, , buf
    Close #fd

    With CreateObject("ADODB.Stream")
        .Type = 1   ' 1=adTypeBinary
        .Open
        .Write buf
        .Position = 0
        .Type = 2   ' 2=adTypeText
        .Charset = "UTF-8"
        ' ReadText...
        .Close
    End With
End Sub

この方法の欠点は、ファイル全体をメモリに読み込んでしまうこと。できれば 1 行ずつ読み込ませたいが、バッファリング制御の実装とか大変そう過ぎて、やってみる気すら起きない。