Windows Mobile におけるフォントキャッシュ

QwicTwit の動画を公開した後、ちまちまいじっていたら、特に変なことをした覚えもないのにスクロールが遅くなってしまって立ち往生。原因を探るべく、色々試してた。

  • プロファイリングしてみよう、と思ったら Windows Mobile な DLL プロジェクトに使えるよさげなプロファイラが見つからなくて断念。
  • 仕方がないので、描画周りで手動で GetTickCount() を埋め込みまくってログ吐かせてみるも、 DrawText() が遅いという何の参考にもならない予想通りの結論に。
  • でも文字描画周りは触ってないしなあ。
  • フォントキャッシュ周りの値を変更しても大差ないし…
  • あれ、前のバージョンに戻しても遅い… 環境がマズいかも!
  • と、フォーマットまでしたのにやっぱり遅い。
  • うーん、あの動きは幻覚だったのか…
  • でも動画という証拠が残っていて俺涙目

単純に BitBlt() でスクロールできてしまえば速いけど、背景画像があるからそうもいかない。じゃあ思い切って、オフスクリーンサーフェス + マスクでスプライト作戦か! とか思い立つも、夢のテクノロジー ClearType の前に打ちひしがれる。いや、さすがにここで RGBA のアルファブレンド書くのは違うだろー…とか考えつつ cairo のコードを眺めてみたりもした。さてどうしたものか。結局詰まってしまって何も進まない。

で、今日も今日とて色々試していたわけです。

HKLM\System\GDI\Glyphcache\limit の値をデフォルト (0x400) に戻して、やっぱりデフォルトは遅いんだなぁと実感した後、適当に 128KB とか 1MB とか変えてみたら、どういうわけかキャッシュの効果が頭打ちになる。といっても、キャッシュサイズが巨大すぎて逆に遅くなったりしている、というわけでもなさそう。あと、同じ文字が一画面に多数出てくるような状態だとやたら高速。あれれ、キャッシュの効き方が偏ってる? どんな実装だよ。とか思いつつ MSDN を漁りながらあることに気がついた。

フォントキャッシュは、 DeleteObject(HFONT) した時点で削除される。

毎回律儀にフォントの取得 & 解放してたのをやめたら一気に爆速になって愕然とした。うおー、そんなことどこにも書いてないじゃないか! EUDC (ユーザ定義文字) 周りのドキュメント にちょこっとそれらしいことが書いてるけど直接関係ないし。というか、如何に DrawText() を高速にするか、あるいは呼び出しを減らすか、という点ばかり注視してたので、そもそもフォントキャッシュが効いていなかったなんて予想もしなかった。フォントの取得や解放自体に時間が掛かるわけじゃないから、なおさら気づきにくい。

というわけで、この 3 週間くらい (気が向いた時だけ) 悩んでた問題が解決したので、ようやく前進できそうな感じ。でも結局、動画の時の速さの要因は謎のまま。もちろん動画よりも今の方が速いんだけど、あれは何だったんだろう。