2015年5月アーカイブ

「SQLアンチパターン」読んだ

RDBMSにてテーブル設計をするときに行いがちな悪いパターンを25個紹介し、何がダメなのか・どう回避すべきなのかを述べている。特定のRDBMS製品によらないように、例として出てくるSQLも極力複数の製品を意識して書いている。

個人的には読んでみてがっかりな本だった。いわゆるGoFデザインパターンを彷彿とさせるような本でありながら、中で語られるのがあまりにも当たり前すぎることばかり。文章自体は丁寧にかつわかりやすく書いているので、結果さくさく読み進めてしまい読み応えが全くない感じ。

こんな本が発売されてしまうのはたぶんあれだ、RDBMSが何なのかががあまりにも理解されなさすぎなのが原因じゃないかと。SQLがコンピュータで使われる言語だという安直な理由だけで、プログラマが使うプログラミング言語とごっちゃにされてしまい、結果RDBMSの設計思想を全く理解しないままにプログラマが適当に使ってしまっているのが原因じゃなかろうかと。本文で頻繁にORMが出てきているあたりにも、RDBMSをただのデータストアに使っているだけのフレームワークに踊らされているようなプログラマの存在がどうしてもちらついてしまう。

あとこの本って、SQLという問い合わせ言語の本ではなくて、RDBMSとテーブル設計についての本だよね。タイトル詐欺じゃないかとは思う。

と、ものすごく悲観的に評論してしまったけど、中身はものすごくまっとうで大事なことばかりなので、RDBMSを使い始めたばかりだったり独特のテーブル操作に違和感があったりするような初心者には安心しておすすめしていいでしょう。逆に、Oracleの資格持ってたり「実践ハイパフォーマンスMySQL」とかを読んでいるような人には、当たり前すぎて退屈な本でしょう。

Apacheを使ってReverseProxyしていて、フロント(クライアント)からのアクセスをhttpsで、バックエンドをhttpでやっているようなケースでの問題。mod_proxyのドキュメント通りに、おおむね以下のような設定を書いているハズ。

<VirtualHost *:443>
  (...snip...)
  ProxyPass /bugzilla http://192.168.1.3/bugzilla
  ProxyPassReverse /bugzilla http://192.168.1.3/bugzilla
  (...snip...)
</VirtualHost>

ProxyPassReverseは、バックエンドがLocationヘッダでリダイレクトしようとするような場合に、pathをReverseProxyっぽく(クライアントの都合のいいように)書き換えるオプション。このとき、Locationが相対パスなら特に問題ないものの、絶対パス(特にhttp://がある)場合に問題になる。つまり、ReverseProxyはpathは書き換えるもののプロトコルはhttpのままとなり、クライアントはhttpsからhttpにリダイレクトされてしまう。たぶんhttp/httpsの関係が逆でも同じことが起こるハズ。

これを解決する方法はググるとおおむね2つ見つかる。1つめは「もう一度リダイレクトする」ことで、つまり、クライアントがhttpでアクセスしたらhttpsにアクセスするようにしておく。何度もリダイレクトするのがムダなものの、負荷さえ気にしなければそれほど悪くもない。ただ、デフォルトポート(httpを80, httpsを433)にやっているならこういう対処も可能だけど、ポート番号を変更している場合、ポート番号はそのままにプロトコルだけ切り替わってしまい、httpsで待ち受けるポートにhttpでアクセスされることになってしまうので、この方法は使えない。

もう1つが「X-FORWARDED-PROTO」を使う方法で、ReverseProxyがバックエンドにリクエストするとき「X_FORWARDED_PROTO: 'https'」を付加することでバックエンドのアプリに指示を出してバックエンドのアプリに適切なLocation: を吐かせるようにする。

<VirtualHost *:443>
  (...snip...)
  RequestHeader set X_FORWARDED_PROTO 'https'
  (...snip...)
</VirtualHost>

ただ、「X-FORWARDED-PROTO」はあくまでアプリに指示をするだけのもので、Ruby on Rails だとこれを解釈してくれるものの、bugzillaなどそうでないアプリの方が圧倒的に多い気がする。ReverseProxyがnginxの場合だと「proxy_redirect http:// https://;」なんて方法があるようだけど、Apacheだとあまり適切な設定項目がない。いろいろ悩んだ結果、力業であることを承知で下記のように対処。

<VirtualHost *:443>
  (...snip...)
  Header edit Location ^http https
  ProxyPass /bugzilla http://192.168.1.3/bugzilla
  ProxyPassReverse /bugzilla http://192.168.1.3/bugzilla
  (...snip...)
</VirtualHost>

HeaderディレクティブについてはApacheのmod_headersの英語ドキュメントを参照。なぜか日本語版には Header editが書いてない。日本語のドキュメントだけ見てたときは「Apache 2.4からか?」と勘違いしてしまった。

Movable Typeが遅すぎる

結論だけ先に言うとMovable Typeの管理画面を高速化するプラグイン:CachePermsだけ見てればいい気がします。ここに書かれてる点以外はほとんど効果なし。

惰性でかれこれ10年以上Movable Type使ってるんですが、当初からの悩みが「遅い」こと。昔はしょぼいマシンで動かしていたので仕方ないかなぁと思っていたものの、それなりに最近のマシンに置き換えてもやっぱり遅いので、マジメに対処考えてみることにした。ちなみに、検索が遅いのは自分で検索用PHP書くことで対処してます。

漠然と「遅い」じゃ定量的じゃないので、まずは計ってみます。

[rarul@mana mt]$ time perl mt.cgi > /dev/null
real    0m1.216s
user    0m1.115s
sys     0m0.098s
[rarul@mana ~]$ cat /proc/cpuinfo |grep model |grep name
model name      : Intel(R) Celeron(R) CPU  N2820  @ 2.13GHz
model name      : Intel(R) Celeron(R) CPU  N2820  @ 2.13GHz
[rarul@mana ~]$ cat /proc/meminfo |grep MemTotal
MemTotal:        7953060 kB

普段のload averageは0.00、swapなしio詰まりもなし。これで1.2秒とか正気の沙汰じゃない。続けて少しがんばってみます。

[rarul@mana mt]$ perl -d:Profile mt.cgi > /dev/null
[rarul@mana mt]$ cat prof.out
time elapsed (wall):   2.0044
time running program:  1.7945  (89.53%)
time profiling (est.): 0.2099  (10.47%)
number of calls:       32525
number of exceptions:  1
(...snip...)

prof.outを見る限り時間かかっているのは、importと一部の呼び出し回数多いメソッド(MT::Component::registry, YAML::Tiny::_read_hash, YAML::Tiny::_read_hash とか)。てか呼び出し回数多いの基準が1000超えとか設計としてどうなんよと、しかもregistryとかpropertiesとかObjectとかDriverとかTemplateとか明らかにメタなクラスが目立つ。試しに、mt.cgiからlib/MT/Bootstrap.pm,lib/MT/App/CMS.pm,と読み進んでみたんですが、なんというか設計がメタメタ(meta)ですね、なにやってるかまったくわからない。たぶんMovable Typeの開発者もどれだけモジュールが読まれて何回呼ばれていてとか全くわからないんじゃないでしょうか。これを改善するのは厳しい、モジュールの粒度や込み込みを根本から改めて最初から書き直すべき次元でしょう。というわけで、中を変更するのはあきらめて、外から何とかするやり方を考える。

内容がかなり怪しいページっぽいけどMovable Type をめっちゃ高速化する20の方法 - 2013年Xmasバージョンを参考にいろいろトライしてみる。

  • 全ステップの再構築は滅多にしないからどうでもいいや。
  • 「メモリ<ディスク<DB(SQL)の順に速い。あるいはDB(SQL)>ディスク>メモリの順に遅い。」とか書いてる段落は明らかにミスリードしているので無視すべき。
  • 「1.File::Cacheプラグインを使う」の段落、File::Cacheってナニ?ファイルアクセスをディスクアクセスと同一視している時点で説明が怪しいのでスキップ。
  • 「2.DBをチューニングする」query_cache_size, sort_buffer_size, key_buffer_size, myisam_max_sort_file_sizeをばかでかくしてもほとんどベンチに差なし。InnoDBに変換してinnodb_buffer_pool_sizeをばかでかくしてもほとんど差なし。
  • 「3.不要なプラグインの退避(削除)」CachePerms, Textile, spamlookup以外をやめて、ようやく0.1秒早くなった!
  • 「4.再構築オプションの適切な選択をする」すでに最低限しか選んでないし。それ以前に再構築じゃない場面も遅すぎる。
  • 「5.PageButeプラグインを使わない」最初から使ってすらいない。
  • 「6.mt-static 以下のファイルをminifyする」なにいってるのかわからないけど、今時gzip圧縮&展開ごときでCPUパワー使い切らないし、それ以前に転送量が問題じゃないし・・・
  • 「7.テンプレートを最適化する、テンプレートキャッシュを活用する」プラグイン減らそうっていった矢先にまた増やすのは・・・てか再構築じゃなくても遅いんだし・・・
  • 「8. psgi/FastCGIを使う」これは効果あった。2/3くらいになった。気持ち的にFastCGI使うのはなぁと思ったけど。(Apacheのmod_fastcgi経由じゃないと動かせないのでベンチは取らず)
  • 「9.ハイスペックサーバーにする」N2820がハイスペックだとは言わないけど、いってもCPU速度が倍程度でしょ。
  • 「10.クライアントマシン(CMSを操作する側のマシン)をハイスペックにする」明らかにサーバスクリプト処理が遅いのにこの人ナニいってんの・・・
  • 「11.PHPアクセラレータを導入する」プラグインとかそもそも最低限にしてるし。
  • 「12.不要なプラグインの退避(削除)」いやだから使ってないし。
  • 「13.静的化できる部分を静的化する」すでに静的化してるし、mt.cgiのトップにアクセスするのすら遅いのには関係ないし。
  • 「14.キャッシュを使う」PHPアドオン使ってないから、Smartyとか関係ない・・・
  • 「15.最新版 DynamicMTMLと Memcached」DynamicMTML使ってない・・・
  • 「16.Minify、画像のBase64エンコード、gzip圧縮」だから転送量とかgzipのCPU時間とかはまったく影響してないんだってば。
  • 「17.フロントサーバーとアプリケーションサーバーの分離、あるいはCDN」たくさんのリクエストを処理したいとかいうスループットの問題じゃなくて、1つのアクセスが完了するまでの時間のレイテンシが問題なんですよ。目の前にあるマシンにアクセスするのにCDNはさすがにない。
  • 「18.PerlプラグインではMT->Requestでデータを使いまわす、PHPプラグインでは、$app->stash、$ctx->stashでデータを使いまわす」プラグインは(略
  • 「19.PSGIで動かす、キャッシュを活用する」FastCGI使う前提ならPSGIはあんま関係ないような。そうでもないかな。Movable Type 6.0かららしいのでスキップ。「Data APIから取ってキャッシュする」ってMovable Type本体をすでにムシしてるよね。
  • 「20.ミッションクリティカルなサービスで、読み出し系のものは、静的JSONのパブリッシュも検討しよう」結局13.とあんま言ってること変わらない。

結局、FastCGIにするのと、不要プラグインを消しまくるのとしか参考にならなかった。

他サイトないかなと探してて見つかったCachePermsが少し効果あり。中身見てみる限り、呼び出し回数が多い __deep_localize_labels や MT::Component::registry の効率悪い書き方の箇所をバイパスしてくれているっぽい。ただ、悲しいな、他にも呼び出し回数多くて遅いサブルーティンあるし、そもそものロードするモジュール多い問題はどうしようもないし。

ちびちびチューニングしたりMovable Type本体バージョンアップしたりしてみたものの、これくらいが限界でした。

[rarul@mana mt]$ time perl mt.cgi > /dev/null
real    0m1.129s
user    0m1.050s
sys     0m0.075s
[rarul@mana mt]$ perl -d:Profile mt.cgi > /dev/null
[rarul@mana mt]$ cat prof.out
time elapsed (wall):   1.8528
time running program:  1.6576  (89.46%)
time profiling (est.): 0.1952  (10.54%)
number of calls:       29947
(...snip...)

prof.out httpd経由ではFastCGIにしたので、これの2/3くらいの時間。ましにはなったがそれでも体感的には遅い。

とまぁ、プラグインやアドオンてんこ盛りにしてしまって遅いというならまだしも、デフォ状態でも遅いという話ならばほとんど打つ手なし。早く他のに乗り換えましょう。

MySQLを用いてクリティカルなシステムを構築するための知識をまとめた本。1秒当たり数千から数万トランザクションを処理するようなWebアプリケーションを主に想定して書いている。

ページ数が多くてしかも内容が重かった。MySQLの使い方はわかっているという前提だが、実際には、プロセッサ・ストレージ・RAM・ネットワーク・OSの一般的な知識は必須で、書かれていることを正確に理解するには相当熟練されていないと厳しい。プログラマ向けというよりは、どちらかというとシステム・サーバ管理者向けかもしれない。

内容は、ベンチマーク・ボトルネック調査・最適化・レプリケーション・バックアップとリカバリ、という感じに範囲が広い。また、MySQLとマジメに対面しているからこそ、MySQLじゃない部分についても注意深く検証するよう語りかける部分が多い。逆に、注意深く書くからこそ、例外を念頭に断定的に書かず、結果回りくどい文章になっている箇所が多い。

英語を直訳したようなわかりにくい表現になっている箇所が多いのが気になった。また、原盤がということになるんだろうけど、結論をわかりやすくは書かずに回りくどく書いているのも気になった。ページ数が多いからこういう本は読むのが疲れるんだよなぁ・・・

実は、第1版を買って読まずに積み本していたら第2版が出ていて、で第2版を買ってまた読まずに積み本していたら第3版が出ていて・・・ということが読み始める前に発覚。第1版から第2版は大幅改訂でページ数もめちゃ増えてるけど、第2版から第3版は比較的マイナーな変更っぽかったので、第3版を買うのは今回はやめといた。O'REILLYのページによれば第2版から第3版の差分は以下らしいのでまぁ大丈夫かなっと。

● 追加された項目
- ソリッドステートストレージ
- クラウドでのMySQL
● 強化された項目
- ベンチマークとプロファイリング
- スキーマの最適化とインデックス
- 高可用性を新規の章に
- ストレージエンジンの紹介の改訂
- クエリパフォーマンスのケーススタディ
- パーティショニング
- クエリオプティマイザ
● 削除
- MySQLサーバーの状態が章から付録に移動
- セキュリティの章が消えた

いや、「ソリッドステートストレージ」は超大事なような。ストレージの性能・特性が大きく変わった革命だから、ここだけを特出しでフォローするほどの価値がある内容のハズ。

MySQLの性能や可用性を気にするような運用をする人はぜひ読むべきでしょう。同時に、ページ数・内容とも重いので、読むときは心して読んだ方がよいでしょう。

「Binary Hacks」読んだ

今更読んだのかよ、と言われるくらい積み本状態でしたが・・・

UNIXシステムプログラミングでの小ネタ集のようにまとめたもの。ELF, object file, dwarf, gcc, ld 回りの話を100個に小分けしてネタ紹介している。

私がかなり昔にELF Golfの話を見ていたせいか、このBinary Hacksの本はこういうELF Golfのような変なことをやるための話ばかりと思ってしまっていた。けど、いざ読んでみるとものすごく普通の話ばっかりだった。

話の内容としては、kernelやらコンパイラやらブートローダやらシステムコールやらライブラリロードやらのよくある話・・・とまでいうと言い過ぎで、ぜひ覚えておきたい話が大部分。Linuxの組み込みソフトをやるなら知っておかないといけないような話。まぁ最近はいくらLinuxとはいえほとんどがベンダから提供されるツール使えばほとんど気にせずこれらの恩恵を受けられる。けど、まれに起こる変なバグを追おうと思ったら・・・ね。

ただ、本が出たのが2006年11月で今から見ればかなり昔、また書かれた当時から見てもベースとしてるツールや環境が古い(Linux-2.4とか)、いくつか紹介されてるツールも相当古いので今この本の内容をそのまま適用するのには注意がいる。

また、小ネタを書いている人によっては x86-linux-gccだけを考えていたりというのも少し注意必要かも。最近はむしろx86-64だし、gccからllvmに移り変わろうとしているし、Mac OSなんてFreeBSDだし、またこの手の話はむしろarmv7だし、これからはarmv8が求められるところだし。

少し変わったとことして、第4章にセキュアプログラミングHackとして、バグを起こしがちの話やメモリリークの検出なんかの話もある。この本の趣旨からは少しずれてるきもするけど、話としては重要なのが多い。系統としては、こういうやつとかこういうやつに近いと思う。

この手のUNIXシステム回りのプログラムをやる人に向けては、他にこれと言った本もないので、読んで損はないと思う。ただ少し内容が古いのがなぁ。てか他にこの手の話がある程度体系立てられた本ってないの?

「Effective Perl 第2版」読んだ

Perlを一応は書くことができるというような人を対象に、よりバグの少ない保守しやすい書き方をするためには何をした方がよいのかを、120個の項目に打ち立てて解説している本。第1版が出たのが10年以上も前なので、その間にPerl回りにあった変化を受けて項目を再構成している。どの項目がどう変わったかを付録Bにまとめていたりもする。

この本のタイトルは間違いなく「Effective C++」を意識していて、序章にもそんな旨が書かれている。Effective C++は私は間違いなく良書だと言い切れるけど、このEffective Perlはと言われるとさすがにそこまではっきりとは言い切れないなぁと思う。

120個の項目に分けて解説しているけど、あまりにも当たり前のことを言ってるだけのがあったり、項目のタイトルだけでは何を守らないといけないのかが簡潔に記述されてなかったり、何かこう項目に洗練さがまだ足りないと感じざるを得ない。そもそも140個ってどうよ、覚えるには数が多すぎるよ。本当の良書を目指すなら、いらないものを削る勇気も必要だよ。

とまぁ、高望みをすればきりがないけど、個々の項目に目を通す限りはまっとうなことが書かれているので、本書のターゲットとしているような人が読む分には十分かと。ただ、「Perl中級者」のような言葉がこの本を語るときによく出てくるけど、あまり中級者向けじゃないよなぁどちらかというと初心者よりの人向けだよなぁと思う。いくつかの項目なんか「このモジュール便利だぜぜひ使おうぜ」って言ってるだけだったりするし。

・・・とかとかいいつつ、「Perlの中級者」「Perlの上級者」ってものが私もよくわからなかったりするんですけどね。なんとなく「Perlの上級者」って、Perlに詳しいと言うよりもPerlのモジュールをCでがりがり書いてるような人が思い浮かんじゃうんですけどね。

というわけで、100行くらいのPerlを書きながら悩んでしまうような初心者向けにちょうどよい本かと思います。

「続・初めてのPerl 改訂第2版」読んだ

初めてのPerlの続編。前作と同じような文体と構成で、主にレファレンス・パッケージ・オブジェクトの話を解説している。

前作が通称「リャマ本」で今回のが「アルパカ本」。体系立ててPerlを学ぼうと思って前作を読んだなら、本作はもはや読まざるを得ないというような話の流れになっている。それくらい話している内容が前作と本作とできっちり役割分担されている。それだけに、前作が改訂第6版までいっているのに本作が改訂第2版までなのは正直どうなんかなぁと思う。改訂が出るタイミングと合っていないと、Perlバージョンアップに本の内容が取り残されたりしたりとか。

で内容はというと、前作同様に解説口調で話が進むので、それほど分量があるようには感じない。のわりに、今や必須とも言えるPerlのレファレンスが前作には一切出ずに本作でいきなり出てくるので、本作は「続」というよりは「上下」の下だといった方がいいんじゃないかと思わなくもない。

レファレンスの他にテストやデストリビューションの話も出てくるけど、このあたりもまだまだ入門的な話にとどまっている。というか、至る所に「詳細はマスタリングPerl読んでくれ」と書かれていて、このあたりもうーんと感じざるを得ない。前作と本作まとめて1冊にした方がいいんじゃないかと思う。でも本当にそうしてしまうと、ごくごくライトにスクリプト言語をやりたいだけの人が困ったりするのだろうか。うーん。

とまぁ批判的に書いてしまいましたが、前作の続編という位置づけで安心して読めます。逆に、前作読んだら本作も読まざるを得ない気がします。

WindowsNT以降のx86プログラムを対象にOllydbgを使って動的解析をしてみるという内容の入門書。解析に必要な知識を一通り解説したあとでOllydbgを使った実践的な解析・・・というかOllydbgの使い方と簡単な演習へ続いている。プログラムの経験がない人をターゲットにしているのでプログラムはあまり出てこないようになっている(とはいえ少しは出てくる)。

本当のプログラム初心者にまで通用するのかは微妙だとは思うものの、解析のための話はおおむね網羅されているように思う。私はこの手の話はx86やWindowsを日頃対象にしてないということもあり、さくさく読めるしかつ内容もそこそこ役立ちそう。ただこの手の本って要するにPCゲームでパラメータ書き換えするようなのが主目的の人に向けられてしまうので、果たして今時のPCゲーム相手にこの程度のやり方で通用するのかどうか疑問に思えてならない。

7章にデバッガによる解析の回避が、8章に法律やモラルの話が出ていたりするのは好感。この手の話ってそう単純じゃなくて、マジメに語るとそれだけで1冊書けるくらい大事な話なので、話の方向はこのままでもっと分量多くしてほしかったなぁと思わなくもない。

この手の話の入門書としては買ってよいと思う。長い間私が買ったのに読んでいない積み本としていたせいで、内容が少し時代と合わなくなってきていないかなぁというところが気がかり、と思っていたら改訂版というかx64対応版が出ていた。

このアーカイブについて

このページには、2015年5月に書かれたブログ記事が新しい順に公開されています。

前のアーカイブは2015年4月です。

次のアーカイブは2015年6月です。

最近のコンテンツはインデックスページで見られます。過去に書かれたものはアーカイブのページで見られます。

月別 アーカイブ

ウェブページ

Powered by Movable Type 7.5.0