<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
    <title>KoshigoeBLOG</title>
    <link rel="alternate" type="text/html" href="http://blog.koshigoe.jp/" />
    <link rel="self" type="application/atom+xml" href="http://blog.koshigoe.jp/atom.xml" />
    <id>tag:blog.koshigoe.jp,2010-01-21://3</id>
    <updated>2010-02-24T13:50:16Z</updated>
    <subtitle>web周辺、mac周辺、php周辺、とか。pythonも？</subtitle>
    <generator uri="http://www.sixapart.com/movabletype/">Movable Type Pro 5.01</generator>

<entry>
    <title>ZenCoding はじめてみた</title>
    <link rel="alternate" type="text/html" href="http://blog.koshigoe.jp/archives/2010/02/zencoding.html" />
    <id>tag:blog.koshigoe.jp,2010://3.1299</id>

    <published>2010-02-24T13:48:17Z</published>
    <updated>2010-02-24T13:50:16Z</updated>

    <summary><![CDATA[        ブログ記事は MT のフォーマットをなしにして書くので、div&gt;p を作るのがすごい楽。     EmacsWiki: Zen Coding           いつも、Emacs でドラフトを書いて、それを MT のテキストエリアにコピペするわけですが、フォーマットなしなので多少 HTML タグを書く必要があります。これを *scratch* で書いていたので、何のサポートもなく、ひたすらタイプしていました。           最近 ZenCoding を知って、その Emacs 版を使ってみることにしました。そしたら、「div&gt;p C-RET RET」で段落のコンテナを作ってもらえるじゃないですか。まあ、この程度しか使ってないのであれなんですが、個人的にすごく楽になったように錯覚してます。           導入を決めたポイントはいくつかあります。                  プレビューがある                 テスト(spec)書く時に使う CSS セレクタを覚えられそう                 楽できそう                未だに...]]></summary>
    <author>
        <name>koshigoe</name>
        <uri>http://blog.koshigoe.jp/</uri>
    </author>
    
        <category term="tech" scheme="http://www.sixapart.com/ns/types#category" />
    
    <category term="zencoding" label="zencoding" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="ja" xml:base="http://blog.koshigoe.jp/">
        <![CDATA[<div>
  <p>
    ブログ記事は MT のフォーマットをなしにして書くので、div&gt;p を作るのがすごい楽。<br />
    <a href="http://www.emacswiki.org/emacs/ZenCoding">EmacsWiki: Zen Coding</a>
  </p>
</div>
<div>
  <p>
    いつも、Emacs でドラフトを書いて、それを MT のテキストエリアにコピペするわけですが、フォーマットなしなので多少 HTML タグを書く必要があります。これを *scratch* で書いていたので、何のサポートもなく、ひたすらタイプしていました。
  </p>
</div>
<div>
  <p>
    最近 ZenCoding を知って、その Emacs 版を使ってみることにしました。そしたら、「div&gt;p C-RET RET」で段落のコンテナを作ってもらえるじゃないですか。まあ、この程度しか使ってないのであれなんですが、個人的にすごく楽になったように錯覚してます。
  </p>
</div>
<div>
  <p>
    導入を決めたポイントはいくつかあります。
  </p>
  <ol>
    <li>
      プレビューがある
    </li>
    <li>
      テスト(spec)書く時に使う CSS セレクタを覚えられそう
    </li>
    <li>
      楽できそう
    </li>
  </ol>
</div>
<div>
  <p>
    未だに CSS セレクタを把握してないのは恥ずかしい限りですが、一石二鳥な感じがあってすごく期待しています。まだ考えながら使っているので、本当に楽になったわけではないんですが、期待感があるのでしばらくは使い続けるつもりです。正直、なんとかスニペットは使い忘れるんですが、これなら使い忘れることはないかな、という期待感もあります。
  </p>
</div>
<div>
  <p>
    というわけで、ZenCoding の背景などは全く把握してませんが、CSS セレクタ書いて C-RET RET したら HTML を書き込んでくれるツールとして使っていこうと思います。
  </p>
</div>
]]>
        
    </content>
</entry>

<entry>
    <title>影舞 と DBI と最近の Ruby</title>
    <link rel="alternate" type="text/html" href="http://blog.koshigoe.jp/archives/2010/02/_dbi_ruby.html" />
    <id>tag:blog.koshigoe.jp,2010://3.1298</id>

    <published>2010-02-24T13:38:28Z</published>
    <updated>2010-02-24T13:50:58Z</updated>

    <summary>        社内のサーバをリプレースする作業が進行中。           その中の影舞を移行する作業を手伝ったわけですが、どうも比較的新しいバージョンの DBI や Ruby で動かすには、少々問題がある様でした。今は Redmine をメインで利用していますが、影舞には過去の貴重な情報が詰まっているので、なんとかうまいこと移行しないといけません。ちなみに、影舞は社内のみの公開だったので、バージョンアップをサボって 0.8.6 を使っていました。           まず、Ruby の 1.8.7 を使って動かすためには、セーフレベル絡みで問題がありました。これに関しては、$SAFE = 1 の行を消せばなんとかなる様子でした。ただ、試しに影舞の 0.8.8 を動かしてみたら、その問題は解消されたのか、特に問題になっていませんでした。           問題は DBI 絡みで、DateTime#to_time や DateTime#minute などを呼ぼうとして undefined method などとなっていました。古いサーバでは DBI も古いバージョン(0.1.1)を使っていて、このバージョン...</summary>
    <author>
        <name>koshigoe</name>
        <uri>http://blog.koshigoe.jp/</uri>
    </author>
    
        <category term="tech" scheme="http://www.sixapart.com/ns/types#category" />
    
    <category term="ruby" label="ruby" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="ja" xml:base="http://blog.koshigoe.jp/">
        <![CDATA[<div>
  <p>
    社内のサーバをリプレースする作業が進行中。
  </p>
</div>
<div>
  <p>
    その中の影舞を移行する作業を手伝ったわけですが、どうも比較的新しいバージョンの DBI や Ruby で動かすには、少々問題がある様でした。今は Redmine をメインで利用していますが、影舞には過去の貴重な情報が詰まっているので、なんとかうまいこと移行しないといけません。ちなみに、影舞は社内のみの公開だったので、バージョンアップをサボって 0.8.6 を使っていました。
  </p>
</div>
<div>
  <p>
    まず、Ruby の 1.8.7 を使って動かすためには、セーフレベル絡みで問題がありました。これに関しては、$SAFE = 1 の行を消せばなんとかなる様子でした。ただ、試しに影舞の 0.8.8 を動かしてみたら、その問題は解消されたのか、特に問題になっていませんでした。
  </p>
</div>
<div>
  <p>
    問題は DBI 絡みで、DateTime#to_time や DateTime#minute などを呼ぼうとして undefined method などとなっていました。古いサーバでは DBI も古いバージョン(0.1.1)を使っていて、このバージョンを上げてしまうと件のメソッドを拡張した Time や Timestamp を使わなくなってしまうらしく難儀しました。突然 DateTime を使うようになった(?)事も問題の原因だったようです。
  </p>
</div>
<div>
  <p>
    dbi-0.1.1 の野良 gem を作って解決を試みたりしましたが、今度は dbd-mysql のパスが変わっていた事で別の問題が発生したりして泥沼の予感がひしひしと。なんだか、DBD/Mysql/Mysql だかを呼ぼうとするわけですが、dbd-mysql は lib/dbd/ と小文字のディレクトリしかなかったり、よくわからない状況でした。
  </p>
</div>
<div>
  <p>
    あまり時間をかけていられなかったので、最後の望みをかけて影舞のリポジトリの 0.8 ブランチを使ってみることにしました。これは、色々と情報をあさっていく中で、影舞で DateTime#to_time メソッドを追加したというコミットログがみつかったからです。
  </p>
</div>
<div>
  <p>
    結果、なんとか動いている様に見えています。とりあえず新規レポートが書けて、返信できて、一覧や詳細を見られれば問題ないので、しばらくは様子見でいいかなという状況です。
  </p>
</div>
<div>
  <p>
    そんなこんなで、近々社内システムを運用しているサーバが強化される予定です。
  </p>
</div>
]]>
        
    </content>
</entry>

<entry>
    <title>Apache の mod_filter を使えるようになりたい</title>
    <link rel="alternate" type="text/html" href="http://blog.koshigoe.jp/archives/2010/02/apache_mod_filt.html" />
    <id>tag:blog.koshigoe.jp,2010://3.1297</id>

    <published>2010-02-20T11:35:20Z</published>
    <updated>2010-02-20T11:36:19Z</updated>

    <summary>        Apache でのコンテント圧縮のやり方を忘れて調べている最中に、AddOutputFilterByType は 2.1 以降で非推奨という事を知ったので。           そもそも、mod_filter が何をどうするものかさっぱり知らないので、その調査から始めているところです。今のところ、ダイナミックな設定を可能とする柔軟性があること、HTTP リクエスト、HTTP レスポンス、環境変数を元にしたフィルタのディスパッチが可能だという事くらいしか把握してません。          KOSHIGOE学習帳 - [Apache] mod_filter           プロトコル・ハンドリングのところが、いまいちよく理解できません。コンテント・フィルタ・モジュールの互換性維持を補助するための仕組み、という感じでしょうか。とりあえず mod_filter の機能要件を満たさないモジュールを、mod_filter で利用するための仕組みと考えています。           ところで、mod_filter は使われてるんでしょうか？コンテント圧縮についてググってみた限り、AddOutputFil...</summary>
    <author>
        <name>koshigoe</name>
        <uri>http://blog.koshigoe.jp/</uri>
    </author>
    
        <category term="tech" scheme="http://www.sixapart.com/ns/types#category" />
    
    <category term="apache" label="apache" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="mod_filter" label="mod_filter" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="ja" xml:base="http://blog.koshigoe.jp/">
        <![CDATA[<div>
  <p>
    Apache でのコンテント圧縮のやり方を忘れて調べている最中に、<a href="http://httpd.apache.org/docs/2.2/ja/mod/core.html#addoutputfilterbytype">AddOutputFilterByType</a> は 2.1 以降で非推奨という事を知ったので。
  </p>
</div>
<div>
  <p>
    そもそも、mod_filter が何をどうするものかさっぱり知らないので、その調査から始めているところです。今のところ、ダイナミックな設定を可能とする柔軟性があること、HTTP リクエスト、HTTP レスポンス、環境変数を元にしたフィルタのディスパッチが可能だという事くらいしか把握してません。
    <br />
    <a href="http://w.koshigoe.jp/study/?%5BApache%5D+mod_filter">KOSHIGOE学習帳 - [Apache] mod_filter</a>
  </p>
</div>
<div>
  <p>
    プロトコル・ハンドリングのところが、いまいちよく理解できません。コンテント・フィルタ・モジュールの互換性維持を補助するための仕組み、という感じでしょうか。とりあえず mod_filter の機能要件を満たさないモジュールを、mod_filter で利用するための仕組みと考えています。
  </p>
</div>
<div>
  <p>
    ところで、mod_filter は使われてるんでしょうか？コンテント圧縮についてググってみた限り、AddOutputFilterByType が使われ続けている様な印象です。まあ、ちょっとしか調べてないのであれですけど。単純に Apache 2.0 の方が使われているという感じでしょうか。
  </p>
</div>
<div>
  <p>
    そんなこんなで、mod_filter でのコンテント圧縮に関する記事はゼロではないので、それらを参考にしながら、トライ＆エラーでやってみようと思います。鬼門はブラウザ(端末)対応ですね...。
  </p>
</div>]]>
        
    </content>
</entry>

<entry>
    <title>モバイル用 Google Analytics のライセンス(再び)</title>
    <link rel="alternate" type="text/html" href="http://blog.koshigoe.jp/archives/2010/02/_google_analyti.html" />
    <id>tag:blog.koshigoe.jp,2010://3.1296</id>

    <published>2010-02-04T14:33:13Z</published>
    <updated>2010-02-24T13:52:05Z</updated>

    <summary>        2010/02/04 現在で、PHP, Perl, JSP, ASPX の 4 種類が用意されているわけだけど、これをほか言語に移植することは規約違反？     Google Analytics | Official Website           前にも同じようなことを調べた気がしたら、まさに同じ理由(規約の第13条の(b))で断念してました。     Server Side Google Analytics できる気がしない - KoshigoeBLOG           何が正解か、いまだ正しく理解していませんし、Google に問い合わせてもいませんが、実際どうなんでしょうか？ググれば移植した人は実際にいるわけで、運用しているかはともかくブログ記事で公開していたりしますよね。多言語に移植する程度なら問題ないという事でしょうか。           メンテコストとか考えると、普通に PHP を使えるようにがんばった方が良さそうな気もしつつ...。    ...</summary>
    <author>
        <name>koshigoe</name>
        <uri>http://blog.koshigoe.jp/</uri>
    </author>
    
        <category term="tech" scheme="http://www.sixapart.com/ns/types#category" />
    
    <category term="google" label="google" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="ja" xml:base="http://blog.koshigoe.jp/">
        <![CDATA[<div>
  <p>
    2010/02/04 現在で、PHP, Perl, JSP, ASPX の 4 種類が用意されているわけだけど、これをほか言語に移植することは規約違反？<br />
    <a href="http://www.google.com/intl/ja/analytics/tos.html">Google Analytics | Official Website</a>
  </p>
</div>
<div>
  <p>
    前にも同じようなことを調べた気がしたら、まさに同じ理由(規約の第13条の(b))で断念してました。<br />
    <a href="http://blog.koshigoe.jp/archives/2008/11/server_side_goo.html">Server Side Google Analytics できる気がしない - KoshigoeBLOG</a>
  </p>
  <p>
    何が正解か、いまだ正しく理解していませんし、Google に問い合わせてもいませんが、実際どうなんでしょうか？ググれば移植した人は実際にいるわけで、運用しているかはともかくブログ記事で公開していたりしますよね。多言語に移植する程度なら問題ないという事でしょうか。
  </p>
</div>
<div>
  <p>
    メンテコストとか考えると、普通に PHP を使えるようにがんばった方が良さそうな気もしつつ...。
  </p>
</div>]]>
        
    </content>
</entry>

<entry>
    <title>gem2rpm と &quot;~&gt;&quot;</title>
    <link rel="alternate" type="text/html" href="http://blog.koshigoe.jp/archives/2010/01/gem2rpm.html" />
    <id>tag:blog.koshigoe.jp,2010://3.1295</id>

    <published>2010-01-28T15:47:43Z</published>
    <updated>2010-01-28T15:49:34Z</updated>

    <summary>        gem のバージョン指定(Gem::Requirement)で &quot;~&gt;&quot; という指定ができるけど、RPM ではできない(ですよね？)件。     RubyForge: Gem to rpm converter: Project Info           gem2rpm の中(gem2rpm.rb)で、Gem::Requirement を拡張していて、Gem::Requirement#to_rpm というメソッドを追加しています。このメソッドは、gem の spec に記載(?)されている依存ライブラリのバージョン番号を、RPM にふさわしいバージョン番号に変換する役割を担います。           この to_rpm メソッドは、gem2rpm のバージョン 0.6.0 現在、ほぼ素通りとなっています。やっていることは、&quot;&gt; 0.0.0&quot; だった場合に &quot;&quot; に置換するのみです。&quot;~&gt;&quot; が使われていても、素通りしてしまうため、RPM に蹴られてしまいます。           gem2rpm は、2008/10/06 のリリースで止まっているので、&quot;~&gt;&quot; に対応しないまま今日に至る、...</summary>
    <author>
        <name>koshigoe</name>
        <uri>http://blog.koshigoe.jp/</uri>
    </author>
    
        <category term="tech" scheme="http://www.sixapart.com/ns/types#category" />
    
    <category term="gem2rpm" label="gem2rpm" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="ruby" label="ruby" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="ja" xml:base="http://blog.koshigoe.jp/">
        <![CDATA[<div>
  <p>
    gem のバージョン指定(Gem::Requirement)で "~>" という指定ができるけど、RPM ではできない(ですよね？)件。<br />
    <a href="http://rubyforge.org/projects/gem2rpm/">RubyForge: Gem to rpm converter: Project Info</a>
  </p>
</div>
<div>
  <p>
    gem2rpm の中(gem2rpm.rb)で、Gem::Requirement を拡張していて、Gem::Requirement#to_rpm というメソッドを追加しています。このメソッドは、gem の spec に記載(?)されている依存ライブラリのバージョン番号を、RPM にふさわしいバージョン番号に変換する役割を担います。
  </p>
  <p>
    この to_rpm メソッドは、gem2rpm のバージョン 0.6.0 現在、ほぼ素通りとなっています。やっていることは、"> 0.0.0" だった場合に "" に置換するのみです。"~>" が使われていても、素通りしてしまうため、RPM に蹴られてしまいます。
  </p>
</div>
<div>
  <p>
    gem2rpm は、2008/10/06 のリリースで止まっているので、"~>" に対応しないまま今日に至る、ということでしょう("~>" の追加がいつ行われたのかは把握していません)。
  </p>
</div>
<div>
  <p>
    なんでこんな話をしているかというと、actionpack-2.3.5 の RPM を作成する必要があり、その中で rack のバージョン指定 "~> 1.0.1" に遭遇したわけです。なので、どうにかして gem2rpm を "~>" に対応させる必要があるわけなのです(gem2rpm を使わない、というのもありですが...)。
  </p>
</div>
<div>
  <p>
    そんな訳で、RPM 作成どころか SRPM を作成するところまでは試していませんが、以下のような修正でごまかしてみようかと思っています。手元では RPM をビルドする環境が整っていないので、検証は後ほど。
  </p>
<pre class="diff"><span style="color: #888822;">--- gem2rpm.rb.orig     <span style="">2010</span><span style="">-01</span><span style="">-29</span> <span style="">00</span>:<span style="">19</span>:<span style="">42.000000000</span> <span style="">+0900</span></span>
<span style="color: #888822;">+++ gem2rpm.rb  <span style="">2010</span><span style="">-01</span><span style="">-29</span> <span style="">00</span>:<span style="">28</span>:<span style="">15.000000000</span> <span style="">+0900</span></span>

<span style="color: #440088;">@@ <span style="">-24</span>,<span style="">15</span> <span style="">+24</span>,<span style="">20</span> @@</span>
 module Gem
   class Requirement
     def rpm_version_transform<span style="">&#40;</span>version<span style="">&#41;</span>
<span style="color: #991111;">-      if version == &quot;&gt; <span style="">0.0</span><span style="">.0</span>&quot;</span>

<span style="color: #991111;">-        version = &quot;&quot;</span>
<span style="color: #00b000;">+      case version</span>
<span style="color: #00b000;">+      when &quot;&gt; <span style="">0.0</span><span style="">.0</span>&quot;</span>
<span style="color: #00b000;">+        <span style="">&#91;</span>&quot;&quot;<span style="">&#93;</span></span>
<span style="color: #00b000;">+      when /^~&gt; <span style="">&#40;</span>.+<span style="">&#41;</span>$/</span>
<span style="color: #00b000;">+        v = Gem::Version.new<span style="">&#40;</span>$<span style="">1</span><span style="">&#41;</span></span>

<span style="color: #00b000;">+        <span style="">&#91;</span>&quot;&gt;= #<span style="">&#123;</span>v.version<span style="">&#125;</span>&quot;, &quot;&lt; #<span style="">&#123;</span>v.bump<span style="">&#125;</span>&quot;<span style="">&#93;</span></span>
<span style="color: #00b000;">+      else</span>
<span style="color: #00b000;">+        <span style="">&#91;</span>version<span style="">&#93;</span></span>
       end
<span style="color: #991111;">-      version</span>

     end
&nbsp;
     def to_rpm
       result = as_list
<span style="color: #991111;">-      return result.map <span style="">&#123;</span> |version| rpm_version_transform<span style="">&#40;</span>version<span style="">&#41;</span> <span style="">&#125;</span></span>
<span style="color: #00b000;">+      return result.inject<span style="">&#40;</span><span style="">&#91;</span><span style="">&#93;</span><span style="">&#41;</span> <span style="">&#123;</span>|res, version| res += rpm_version_transform<span style="">&#40;</span>version<span style="">&#41;</span> <span style="">&#125;</span></span>

     end
&nbsp;
   end</pre>
</div>]]>
        
    </content>
</entry>

<entry>
    <title>script コマンドを実行して作られるプロセスの数</title>
    <link rel="alternate" type="text/html" href="http://blog.koshigoe.jp/archives/2010/01/script.html" />
    <id>tag:blog.koshigoe.jp,2010://3.1294</id>

    <published>2010-01-22T17:26:37Z</published>
    <updated>2010-01-22T17:28:40Z</updated>

    <summary> CentOS5(x86_64) の script コマンドを実行すると、script という名前で 2 つのプロセスが存在するのは、なんでだろうか。OSX と FreeBSD では script という名前では 1 つしか存在しないのに。 どこに情報があるかわからなかったので ftp://ftp.kernel.org/pub/linux/utils/util-linux/util-linux-2.12a.tar.gz に含まれるソース(util-linux-2.12a/misc-utils/script.c)を読んでみました。 親プロセスが fork() して子プロセスを生成する 子プロセスが fork() して孫プロセスを生成する まず、都合 3 プロセスが生成されることがわかりました。 そのうち、孫プロセスはわかりやすく、execl でシェルを起動させていました。bash であれば、ps に出てくる名前は &quot;bash -i&quot; になるので、script が複数存在する件とは関係ないこともわかりました。 子プロセスは、pty のマスタから read() で読み続け、読み込んだ内容はログファイルに書き出してい...</summary>
    <author>
        <name>koshigoe</name>
        <uri>http://blog.koshigoe.jp/</uri>
    </author>
    
        <category term="tech" scheme="http://www.sixapart.com/ns/types#category" />
    
    
    <content type="html" xml:lang="ja" xml:base="http://blog.koshigoe.jp/">
        <![CDATA[<p>
CentOS5(x86_64) の script コマンドを実行すると、script という名前で 2 つのプロセスが存在するのは、なんでだろうか。OSX と FreeBSD では script という名前では 1 つしか存在しないのに。
</p>
<p>
どこに情報があるかわからなかったので ftp://ftp.kernel.org/pub/linux/utils/util-linux/util-linux-2.12a.tar.gz に含まれるソース(util-linux-2.12a/misc-utils/script.c)を読んでみました。
</p>
<ul>
<li>親プロセスが fork() して子プロセスを生成する</li>
<li>子プロセスが fork() して孫プロセスを生成する</li>
</ul>
<p>
まず、都合 3 プロセスが生成されることがわかりました。
</p>
<p>
そのうち、孫プロセスはわかりやすく、execl でシェルを起動させていました。bash であれば、ps に出てくる名前は "bash -i" になるので、script が複数存在する件とは関係ないこともわかりました。
</p>
<p>
子プロセスは、pty のマスタから read() で読み続け、読み込んだ内容はログファイルに書き出しています。read() が 0 以下を返した場合に、読み込みのループから抜けて終了処理に移る様です。
</p>
<p>
親プロセスは、まず SIGWINCH シグナルのハンドラを登録しています。そして、標準入力から read() で読み込んだ内容を pty のマスタに書き込み続け、read() が 0 以下を返したら終了処理に移る様です。
</p>
<p>
どうやら、pty がキーワードな様子。プロセスも pty もよくわかってないわけですが、よく見れば孫プロセスがシェルを起動する際にスレーブに触っているので、シェルから書き込んだ内容を親子が使っている様な空気を感じます。
</p>
<p>
孫プロセスから流れてくるデータを子プロセスがファイルに書き込んでいるという感じでしょうか。親プロセスが標準入力からマスタに書き込んでいるのは、シェルに出力する必要があると言うことでしょうか(シェル側で読み取って何かに使う？)。
</p>
<p>
んー、親が延々と標準入力を読み続けているから、親プロセスが生き続けているということでなんでしょうか。それとも、read() が返らないとかでしょうか。
</p>
<p>
というわけで、使い方を間違えているのか、この状態(親子孫が生き続ける)が自然なのか、今の自分では判断がつきませんでした。
</p>
<hr />
<p>
OSX や FreeBSD の script のソースがどこにあるかわからず読んでいないので、Linux と BSD とでプロセスの数が異なるのが、script の実装が異なるのか、もっと下のところで違いがあるのか、わかりません。
</p>]]>
        
    </content>
</entry>

<entry>
    <title>MT5 にアップグレードしてみた</title>
    <link rel="alternate" type="text/html" href="http://blog.koshigoe.jp/archives/2010/01/mt5.html" />
    <id>tag:blog.koshigoe.jp,2010://3.1293</id>

    <published>2010-01-21T15:55:03Z</published>
    <updated>2010-02-24T13:52:10Z</updated>

    <summary> 理由もなくアップグレード。 なんか、インデックスページが賑やかになってよいです。 ほぼ、新規インストールなので、プロフィール的なリンクとか、色々と削れてますが、そのうち付け加えたりするかと思います。 2009 年はブログ記事の数もそうですが、だいぶ沈滞した年でした。今年は、そこそこ動いてみようかなと思ったり、思わなかったりのこの頃です。 ...</summary>
    <author>
        <name>koshigoe</name>
        <uri>http://blog.koshigoe.jp/</uri>
    </author>
    
        <category term="tech" scheme="http://www.sixapart.com/ns/types#category" />
    
    
    <content type="html" xml:lang="ja" xml:base="http://blog.koshigoe.jp/">
        <![CDATA[<p>
理由もなくアップグレード。
</p>
<p>
なんか、インデックスページが賑やかになってよいです。
</p>
<p>
ほぼ、新規インストールなので、プロフィール的なリンクとか、色々と削れてますが、そのうち付け加えたりするかと思います。
</p>
<p>
2009 年はブログ記事の数もそうですが、だいぶ沈滞した年でした。今年は、そこそこ動いてみようかなと思ったり、思わなかったりのこの頃です。
</p>]]>
        
    </content>
</entry>

<entry>
    <title>RSpec の stub! とプライベートメソッドの話</title>
    <link rel="alternate" type="text/html" href="http://blog.koshigoe.jp/archives/2009/12/rspec_stub.html" />
    <id>tag:blog.koshigoe.jp,2009://3.1292</id>

    <published>2009-12-05T15:30:59Z</published>
    <updated>2009-12-05T15:34:18Z</updated>

    <summary> プライベートなメソッドを stub! でスタブすると次の example 内でメソッドが消えている、という話を聞きました。 privateのクラスメソッドをスタブにすると、そのメソッドをSpec上で呼び出すときに、undefined method になる - かせいさんとこ example が評価された後、終了処理が行われます。example オブジェクトの after_each_example がこれに該当します。そして、その中で teardown_mocks_for_rspec が実行されます。 teardown_mocks_for_rspec はモックフレームワークで定義されるメソッドで、標準のモックフレームワーク rspec の中では、$rspec_mocks.reset_all が実行される様になっています。 $rspec_mocks.reset_all は、作られた全てのモックオブジェクトに対して rspec_reset を実行します。 rspec_reset はプロキシオブジェクト(Spec::Mocks::Proxy)の reset を実行します。 reset メソッドの中では、clear_...</summary>
    <author>
        <name>koshigoe</name>
        <uri>http://blog.koshigoe.jp/</uri>
    </author>
    
        <category term="tech" scheme="http://www.sixapart.com/ns/types#category" />
    
    <category term="rspec" label="rspec" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="ruby" label="ruby" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="ja" xml:base="http://blog.koshigoe.jp/">
        <![CDATA[<p>
プライベートなメソッドを stub! でスタブすると次の example 内でメソッドが消えている、という話を聞きました。<br />
<a href="http://d.hatena.ne.jp/kasei_san/20091203/p1">privateのクラスメソッドをスタブにすると、そのメソッドをSpec上で呼び出すときに、undefined method になる - かせいさんとこ</a>
</p>
<p>
example が評価された後、終了処理が行われます。example オブジェクトの after_each_example がこれに該当します。そして、その中で teardown_mocks_for_rspec が実行されます。
</p>
<p>
teardown_mocks_for_rspec はモックフレームワークで定義されるメソッドで、標準のモックフレームワーク rspec の中では、$rspec_mocks.reset_all が実行される様になっています。
</p>
<p>
$rspec_mocks.reset_all は、作られた全てのモックオブジェクトに対して rspec_reset を実行します。
</p>
<p>
rspec_reset はプロキシオブジェクト(Spec::Mocks::Proxy)の reset を実行します。
</p>
<p>
reset メソッドの中では、clear_expectations, clear_stubs, reset_proxied_methods, clear_proxied_methods, reset_nil_expectations_warning といったメソッドが順に実行されます。
</p>
<p>
clear_* メソッドは、Array#clear なので特別な事はおきません。今回の問題に関わるのは reset_proxied_methods メソッドです。
</p>
<p>
reset_proxied_methods は、名前の通りプロキシされたメソッド達それぞれを、リセットするというものです。実際のリセットは reset_proxied_method メソッドで行います。
</p>
<p>
reset_proxied_method(method_name) によって、method_name という名前のメソッドと munge(method_name) で得られる名前のメソッドが remove_method によって削除されます。
</p>
<p>
munge(method_name) で得られるメソッドについては、alias_method(method_name, munge(method_name)) で退避してから削除しています。なぜこんな事をするかと言えば、元々存在していたメソッドをスタブで置き換える場合、munge(method_name) という名前で退避していたからです。
</p>
<p>
さて、プライベートメソッドの場合に、reset 後にメソッドが削除されてしまうのはなぜでしょう。元に戻してくれるはずではないのでしょうか。
</p>
<p>
問題は、スタブを作る(定義する) Spec::Mocks::Proxy#define_expected_method の中にあります。メソッドが「応答可能」な場合にのみ、alias_method(munge(original_name), original_name) によってオリジナルを退避します。
</p>
<p>
ここでメソッドの応答／実在の判定に使われているのは、respond_to? と method_defined? です。これらは、いずれもプライベートメソッドについては偽を返す様です。
</p>
<pre>
&gt;&gt; c = Class.new do
     def pub; 1; end
     private
     def pri; 2; end
   end
=&gt; #&lt;Class:0x10194b1a8&gt;
&gt;&gt; obj = c.new
=&gt; #&lt;#&lt;Class:0x10194b1a8&gt;:0x101941db0&gt;
&gt;&gt; obj.respond_to?(:pub)
=&gt; true
&gt;&gt; obj.respond_to?(:pri)
=&gt; false
&gt;&gt; obj.respond_to?(:pri, true)
=&gt; true
&gt;&gt; c.instance_eval do
     p method_defined?(:pub)
     p method_defined?(:pri)
     p private_method_defined?(:pri)
   end
true
false
true
=&gt; nil
</pre>
<p>
一方で、メソッドの置き換えを行う際は、visibility メソッドで public/private/protected を判断し、適した宣言を行っています。
</p>
<pre class="ruby"><span style="color:#9966CC; font-weight:bold;">def</span> define_expected_method<span style="color:#006600; font-weight:bold;">&#40;</span>sym<span style="color:#006600; font-weight:bold;">&#41;</span>
  <span style="color:#9966CC; font-weight:bold;">unless</span> @proxied_methods.<span style="color:#9966CC; font-weight:bold;">include</span>?<span style="color:#006600; font-weight:bold;">&#40;</span>sym<span style="color:#006600; font-weight:bold;">&#41;</span>
    visibility_string = <span style="color:#996600;">&quot;#{visibility(sym)} :#{sym}&quot;</span>

    <span style="color:#9966CC; font-weight:bold;">if</span> target_responds_to?<span style="color:#006600; font-weight:bold;">&#40;</span>sym<span style="color:#006600; font-weight:bold;">&#41;</span>
      munged_sym = munge<span style="color:#006600; font-weight:bold;">&#40;</span>sym<span style="color:#006600; font-weight:bold;">&#41;</span>
      target_metaclass.<span style="color:#9900CC;">instance_eval</span> <span style="color:#9966CC; font-weight:bold;">do</span>
        alias_method munged_sym, sym <span style="color:#9966CC; font-weight:bold;">if</span> method_defined?<span style="color:#006600; font-weight:bold;">&#40;</span>sym<span style="color:#006600; font-weight:bold;">&#41;</span>

      <span style="color:#9966CC; font-weight:bold;">end</span>
      @proxied_methods &lt;&lt; sym
    <span style="color:#9966CC; font-weight:bold;">end</span>
    target_metaclass.<span style="color:#9900CC;">class_eval</span><span style="color:#006600; font-weight:bold;">&#40;</span>&lt;&lt;-EOF, <span style="color:#0000FF; font-weight:bold;">__FILE__</span>, <span style="color:#0000FF; font-weight:bold;">__LINE__</span><span style="color:#006600; font-weight:bold;">&#41;</span>

      <span style="color:#9966CC; font-weight:bold;">def</span> <span style="color:#008000; font-style:italic;">#{sym}(*args, &amp;block)</span>
        __mock_proxy.<span style="color:#9900CC;">message_received</span> :<span style="color:#008000; font-style:italic;">#{sym}, *args, &amp;block</span>
      <span style="color:#9966CC; font-weight:bold;">end</span>

      <span style="color:#008000; font-style:italic;">#{visibility_string}</span>
    EOF
  <span style="color:#9966CC; font-weight:bold;">end</span>
<span style="color:#9966CC; font-weight:bold;">end</span></pre>
<p>
そんな訳で、respond_to?(method_name) が真を返さないメソッドをスタブすると、次の example の時には消されてしまう様です。
</p>
<p>
さて、これは意図通りなのか、バグなのか、モックやスタブを理解していない身としては、判断がつきません…。
</p>]]>
        
    </content>
</entry>

<entry>
    <title>Apache の mod_proxy_balancer のスケジューリングアルゴリズム</title>
    <link rel="alternate" type="text/html" href="http://blog.koshigoe.jp/archives/2009/11/apache_mod_prox.html" />
    <id>tag:blog.koshigoe.jp,2009://3.1291</id>

    <published>2009-11-20T17:12:20Z</published>
    <updated>2009-11-20T17:12:56Z</updated>

    <summary> まじめに調べた事がないと気づかされたので、ドキュメントを頼ってお勉強。 mod_proxy_balancer - Apache HTTP サーバ mod_proxy - Apache HTTP サーバ まず、mod_proxy_balancer では、２種類のアルゴリズムを選択できる。リクエスト回数ベースの Request Counting と、トラフィック量ベースの Weighted Traffic Counting の２種類。設定は、lbmethod で行う。 Request Counting Request Counting は、lbmethod=byrequests とすると有効になる。このスケジューリングアルゴリズムを左右するパラメータは、lbfactor と lbstatus の２つ。 設定パラメータ lbfactor は、ワーカーに割り当てる仕事量を意味する(クオータ)。lbfactor は正規化されるので、Worker[A].lbfactor = 4, Worker[B].lbfactor = 2 とした場合、2:1 の比率で仕事が割り振られる事になる。ドキュメントによれば、割り振られる順序...</summary>
    <author>
        <name>koshigoe</name>
        <uri>http://blog.koshigoe.jp/</uri>
    </author>
    
        <category term="tech" scheme="http://www.sixapart.com/ns/types#category" />
    
    <category term="apache" label="apache" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="mod_proxy_balancer" label="mod_proxy_balancer" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="ja" xml:base="http://blog.koshigoe.jp/">
        <![CDATA[<p>
まじめに調べた事がないと気づかされたので、ドキュメントを頼ってお勉強。
</p>
<ul>
<li><a href="http://httpd.apache.org/docs/2.2/ja/mod/mod_proxy_balancer.html">mod_proxy_balancer - Apache HTTP サーバ</a></li>
<li><a href="http://httpd.apache.org/docs/2.2/ja/mod/mod_proxy.html#proxy">mod_proxy - Apache HTTP サーバ</a></li>
</ul>
<p>
まず、mod_proxy_balancer では、２種類のアルゴリズムを選択できる。リクエスト回数ベースの Request Counting と、トラフィック量ベースの Weighted Traffic Counting の２種類。設定は、lbmethod で行う。
</p>
<h3>Request Counting</h3>
<div>
<p>
Request Counting は、lbmethod=byrequests とすると有効になる。このスケジューリングアルゴリズムを左右するパラメータは、lbfactor と lbstatus の２つ。
</p>
<p>
設定パラメータ lbfactor は、ワーカーに割り当てる仕事量を意味する(クオータ)。lbfactor は正規化されるので、Worker[A].lbfactor = 4, Worker[B].lbfactor = 2 とした場合、2:1 の比率で仕事が割り振られる事になる。ドキュメントによれば、割り振られる順序に影響する様で、[Worker[A], Worker[A], Worker[A], Worker[A], Worker[B], Worker[B]] という順序にはならず、[Worker[A], Worker[A], Worker[B]] という順序になるとの事。正規かによって、A=4, B=2 は A=2, B=1 と全く同じになるという事らしい。
</p>
<p>
スケジューリング処理の内部パラメータ lbstatus は、ワーカーにどの程度の優先度で仕事を割り当てなければならないかを意味する。
</p>
<p>
ここで言うワーカーはロードバランサのメンバを意味し、通常はリクエストを割り振られるリモートホストの事。
</p>
<p>
スケジューリングは以下の様にして行われる。
</p>
<pre>
for each worker in workers
    worker lbstatus += worker lbfactor
    total factor    += worker lbfactor
    if worker lbstatus > candidate lbstatus
        candidate = worker

candidate lbstatus -= total factor
</pre>
<p>
まず、各ワーカーの優先度(lbstatus)を調整し、仕事を割り当てるべきワーカーとして優先度(lbstatus)が最も高いものを選ぶ。最後に、選ばれたワーカーの優先度(lbstatus)からクオータ(lbfactor)の総量を差し引く事で、優先度(lbstatus)の比率を調整する。これを繰り返す事で、設定されているクオータ(lbfactor)に従った割り振りを実現している。
</p>
<p>
A,B,C,D という４つのワーカーが存在し、それぞれ lbfactor=25 と設定されているとする。以下はそれらの初期状態を示している。
</p>
<pre>
#(0)
worker     A   B   C   D
lbfactor  25  25  25  25
lbstatus   0   0   0   0
</pre>
<p>
最初のスケジューリングによって、以下の様にパラメータが変動する。
</p>
<pre>
#(1)
           v
worker     A   B   C   D
lbfactor  25  25  25  25
lbstatus -75  25  25  25
</pre>
<p>
lbstatus の総量は変わらず、優先度の調整がされている事がわかる。以降のスケジューリングによる変遷を以下に示す。
</p>
<pre>
#(2)
               v
worker     A   B   C   D
lbfactor  25  25  25  25
lbstatus -50 -50  50  50
#(3)
                   v
worker     A   B   C   D
lbfactor  25  25  25  25
lbstatus -25 -25 -25  75
#(4)
                       v
worker     A   B   C   D
lbfactor  25  25  25  25
lbstatus   0   0   0   0
</pre>
<p>
25:25:25:25 = 1:1:1:1 と正規化された挙動になっている事がわかる。つまり、[A,B,C,D,...] という順序の繰り返しでワーカーが選択される。
</p>
<p>
途中で、C が無効になった場合は、以下の様に変遷する。
</p>
<pre>
#(2)
               v
worker     A   B   C   D
lbfactor  25  25   0  25
lbstatus -50 -50   0  50
#(3)
                       v
worker     A   B   C   D
lbfactor  25  25   0  25
lbstatus -25 -25   0 -25
#(4)
           v
worker     A   B   C   D
lbfactor  25  25   0  25
lbstatus -75   0   0   0
#(5)
               v
worker     A   B   C   D
lbfactor  25  25   0  25
lbstatus -50 -50   0  25
#(6)
                       v
worker     A   B   C   D
lbfactor  25  25   0  25
lbstatus -25 -25   0 -25
</pre>
<p>
さらに C が復旧した場合は、以下の様に変遷する。
</p>
<pre>
#(7)
                       v
worker     A   B   C   D
lbfactor  25  25  25  25
lbstatus -25 -25   0 -25
#(8)
           v
worker     A   B   C   D
lbfactor  25  25  25  25
lbstatus-100   0   0   0
#(9)
               v
worker     A   B   C   D
lbfactor  25  25  25  25
lbstatus -75 -75  25  25
#(10)
                   v
worker     A   B   C   D
lbfactor  25  25  25  25
lbstatus -50 -50 -50  50
#(11)
                       v
worker     A   B   C   D
lbfactor  25  25  25  25
lbstatus -25 -25 -25 -25
</pre>
<p>
ドキュメントの例では、優先度(lbstatus)の総量が変化していないので、何かしらの調整が入っているのかもしれないが、調整がなかったとしても、ワーカー間での比率は変わらないはず。よくわからないので、ソース(2.2.14)を感じ取る(処理は大雑把に関数名でわかった気になる)。
</p>
<p>
まず、各ワーカーは init_balancer_members 関数で初期化される。初期化処理の順序は、ワーカー配列の並びに従い、ワーカー配列への追加順序は、設定の記述順序に従う。初期化の中で、ワーカーの lbstatus と lbfactor に、設定パラメータの lbfactor (デフォルト 1)が代入されている。
</p>
<p>
この時点で、先述の lbstatus 遷移の例は間違っている気がする。初期時点で、lbfactor の値がセットされている様子。
</p>
<p>
proxy_balancer_pre_request 関数内で、find_best_worker 関数が呼ばれ、その中で設定値 lbmethod に応じた関数を利用して、仕事を割り当てるべきワーカーを選択する。Request Counting (lbmethod=byrequests) では、find_best_byrequests 関数が呼ばれる。
</p>
<p>
選択を行う前の候補ワーカーは、ワーカー配列の先頭。先述の選択時のワーカー走査は、初期か処理同様にワーカー配列の並び順序に従う。
</p>
<p>
ワーカーが有効かどうかは、PROXY_WORKER_IS_USABLE で判断される様子。この戻り値が偽である場合に呼ばれるのが ap_proxy_retry_worker 関数。この関数の中では、lbstatus の調整を行っている様な様子は見られない。mod_proxy_balancer.c や proxy/ 内のソースから lbstatus を探しても、無効ワーカーに関する特別な調整は見当たらなかった。感じ取った範囲では、特別な調整はしていないのではないかと思う。
</p>
<p>
調整がなかったとしても、先述の例による手計算では、比率的に問題にならないはずなので、これ以上は調べない。
</p>
</div>
<h3>Weighted Traffic Counnting</h3>
<div>
<p>
Weighted Traffic Counnting は、lbmethod=bytraffic とすると有効になる。基本的には Request Counting と同様だが、以下の点が異なる。
</p>
<p>
lbfactor は、どれだけのバイト数のトラフィック量を、そのワーカーに処理させたいかを意味する。この値も正規化される。リクエスト数を単純に数えるのではなく、どれだけの転送量を処理したかを数える。
</p>
<p>
ドキュメントには、上記程度の内容しか書かれていない。心もとないので、ソースを感じ取る。ワーカー選択の関数だけ、確認する事にする。
</p>
<p>
使われる関数は、find_best_bytraffic 関数。
</p>
<p>
各ワーカーを走査し、それぞれについて、ワーカーが処理した転送量と読み込んだ量を lbfactor で割り、その和をトラフィック量とする。そして、トラフィック量が最も最小のワーカーが選択される。
</p>
<p>
先述のドキュメント内にあった疑似コードに従うと、以下の様に書ける(はず)。
</p>
<pre>
for each worker in workers
    worker traffic = (worker transferred + worker read) / worker lbfactor
    if worker traffic < current minimum traffic
        candidate = worker
        current minimum traffic = worker traffic
</pre>
<p>
トラフィック量をそのワーカーの lbfactor で割る事で、概ね公平にリクエストを分散させている。
</p>
</div>
<h3>余談</h3>
<div>
<p>
mod_proxy_balancer のスケジューリングアルゴリズムをまじめに知っておこうと思ったきっかけは、期待通りに振り分けられていないのではないかという話を聞いたから。
</p>
<p>
「ある程度の時間で見ると、公平に振り分けられているが、ある瞬間で見ると偏りが見られる事がある。何事か。」という事があったらしい。
</p>
<p>
ここまでの調査を元に考えると、Request Counting (byrequests) を採用していれば、そのような問題は起こらないのではないかと思う。一方で、Weighted Traffic Counnting (bytraffic) を採用していると、トラフィック量次第なので、偏る事は十分考えられる。
</p>
<p>
改めてつついてみると、どうやら bytraffic を採用している雰囲気が…。
</p>
</div>]]>
        
    </content>
</entry>

<entry>
    <title>Resque について調べてメモした</title>
    <link rel="alternate" type="text/html" href="http://blog.koshigoe.jp/archives/2009/11/resque.html" />
    <id>tag:blog.koshigoe.jp,2009://3.1290</id>

    <published>2009-11-08T13:28:06Z</published>
    <updated>2009-11-08T13:28:44Z</updated>

    <summary> GitHub のブログより。 KOSHIGOE学習帳 - [BackgroundJob][Ruby] Resque とは KOSHIGOE学習帳 - [system][osx] Homebrew KOSHIGOE学習帳 - [BackgroundJob][Ruby] Resque の README より 間に Homebrew が挟まっているのは、Resque の README に「OSX なら Homebrew で Redis を簡単にインストールできるぞ！」と書いてあったからです。結局 MacPorts でインストールしましたけど。 モニタリング用ツールも同梱されているのが、自分にとっては興味をそそられるポイントでした。 Redis も Resque を通じて初めて知りました。とはいえ、存在を確認しただけで、詳しい事は知らないままです。データを永続化したり、扱えるデータ種類が色々あったり、操作も豊富だったりといった噂を耳にした程度です。 DelayedJob を知らないので、Resque とどちらがという事はわかりませんが、モニタリング用ツールが同梱されている点で、Resque が気になるなというところ...</summary>
    <author>
        <name>koshigoe</name>
        <uri>http://blog.koshigoe.jp/</uri>
    </author>
    
        <category term="tech" scheme="http://www.sixapart.com/ns/types#category" />
    
    <category term="resque" label="resque" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="ruby" label="ruby" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="ja" xml:base="http://blog.koshigoe.jp/">
        <![CDATA[<p>
GitHub のブログより。
</p>
<ul>
<li><a href="http://w.koshigoe.jp/study/?%5BBackgroundJob%5D%5BRuby%5D+Resque+%A4%C8%A4%CF">KOSHIGOE学習帳 - [BackgroundJob][Ruby] Resque とは</a></li>
<li><a href="http://w.koshigoe.jp/study/?%5Bsystem%5D%5Bosx%5D+Homebrew">KOSHIGOE学習帳 - [system][osx] Homebrew</a></li>
<li><a href="http://w.koshigoe.jp/study/?%5BBackgroundJob%5D%5BRuby%5D+Resque+%A4%CE+README+%A4%E8%A4%EA">KOSHIGOE学習帳 - [BackgroundJob][Ruby] Resque の README より</a></li>
</ul>
<p>
間に Homebrew が挟まっているのは、Resque の README に「OSX なら Homebrew で Redis を簡単にインストールできるぞ！」と書いてあったからです。結局 MacPorts でインストールしましたけど。
</p>
<p>
モニタリング用ツールも同梱されているのが、自分にとっては興味をそそられるポイントでした。
</p>
<p>
Redis も Resque を通じて初めて知りました。とはいえ、存在を確認しただけで、詳しい事は知らないままです。データを永続化したり、扱えるデータ種類が色々あったり、操作も豊富だったりといった噂を耳にした程度です。
</p>
<p>
DelayedJob を知らないので、Resque とどちらがという事はわかりませんが、モニタリング用ツールが同梱されている点で、Resque が気になるなというところです。
</p>]]>
        
    </content>
</entry>

<entry>
    <title>MySQL をチューニングできるように勉強し直し</title>
    <link rel="alternate" type="text/html" href="http://blog.koshigoe.jp/archives/2009/11/mysql_5.html" />
    <id>tag:blog.koshigoe.jp,2009://3.1289</id>

    <published>2009-11-05T16:41:49Z</published>
    <updated>2009-11-05T16:44:52Z</updated>

    <summary> かなり前に本を読んだりして以来、あまり身に付いていない事が気になるので整理。今更感は気にしない。 (『実践ハイパフォーマンス MySQL 第2版』が今月出版されるはずなので、それまでにある程度復習しておきたいというのが、一番の理由というかきっかけだったりする) とりあえず、MySQL のドキュメントから、それらしいページを見繕ってひたすらだらだらとメモ。その後、メモリ関係のチューニングとして、以下の記事にある mymemcheck を書いて演習(?)にしてみました。 DSAS開発者の部屋:5分でできる、MySQLのメモリ関係のチューニング！ 成果は、以下にまとめました。 KOSHIGOE学習帳 - [MySQL] パフォーマンス関連メモ gist: 227178 - GitHub ドキュメントで通常は 2MB(MySQL AB バイナリだと 256KB)とされているスタックが thread_stack でよいのかとか、innodb_log_file_size のデフォルト値は式を満たさない事などが気になりますが、その辺は追々。 ...</summary>
    <author>
        <name>koshigoe</name>
        <uri>http://blog.koshigoe.jp/</uri>
    </author>
    
        <category term="tech" scheme="http://www.sixapart.com/ns/types#category" />
    
    <category term="mysql" label="mysql" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="ja" xml:base="http://blog.koshigoe.jp/">
        <![CDATA[<p>
かなり前に本を読んだりして以来、あまり身に付いていない事が気になるので整理。今更感は気にしない。<br />
(『実践ハイパフォーマンス MySQL 第2版』が今月出版されるはずなので、それまでにある程度復習しておきたいというのが、一番の理由というかきっかけだったりする)
</p>
<p>
とりあえず、MySQL のドキュメントから、それらしいページを見繕ってひたすらだらだらとメモ。その後、メモリ関係のチューニングとして、以下の記事にある mymemcheck を書いて演習(?)にしてみました。<br />
<a href="http://dsas.blog.klab.org/archives/50860867.html">DSAS開発者の部屋:5分でできる、MySQLのメモリ関係のチューニング！</a>
</p>
<p>
成果は、以下にまとめました。
</p>
<ul>
<li><a href="http://w.koshigoe.jp/study/?%5BMySQL%5D+%A5%D1%A5%D5%A5%A9%A1%BC%A5%DE%A5%F3%A5%B9%B4%D8%CF%A2%A5%E1%A5%E2">KOSHIGOE学習帳 - [MySQL] パフォーマンス関連メモ</a></li>
<li><a href="http://gist.github.com/227178">gist: 227178 - GitHub</a></li>
</ul>
<p>
ドキュメントで通常は 2MB(MySQL AB バイナリだと 256KB)とされているスタックが thread_stack でよいのかとか、innodb_log_file_size のデフォルト値は式を満たさない事などが気になりますが、その辺は追々。
</p>]]>
        
    </content>
</entry>

<entry>
    <title>replicate-wild-ignore-table やめて解決したかもしれない</title>
    <link rel="alternate" type="text/html" href="http://blog.koshigoe.jp/archives/2009/10/replicatewildig.html" />
    <id>tag:blog.koshigoe.jp,2009://3.1288</id>

    <published>2009-10-29T13:38:59Z</published>
    <updated>2009-10-29T13:39:35Z</updated>

    <summary> まだ、経過観察中ながら、異常傾向がみられなくなった。 テーブル単位での ignore だから、キャラクタセットの切り替えが(バイナリログからクエリを実行するスレーブサーバでは)本来期待するようには行われなかったという事だと思ってます。 そもそも、replicate-wild-ignore-table の使い方というか、使ってよい条件を満たせていなかったのかもしれません。元々、滅多に使わないテーブルに関する設定だったので、これで収まるならそれはそれでよいかな、といった所です。 本当に解決していたらうれしい限りです。 ...</summary>
    <author>
        <name>koshigoe</name>
        <uri>http://blog.koshigoe.jp/</uri>
    </author>
    
        <category term="tech" scheme="http://www.sixapart.com/ns/types#category" />
    
    <category term="mysql" label="mysql" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="ja" xml:base="http://blog.koshigoe.jp/">
        <![CDATA[<p>
まだ、経過観察中ながら、異常傾向がみられなくなった。
</p>
<p>
テーブル単位での ignore だから、キャラクタセットの切り替えが(バイナリログからクエリを実行するスレーブサーバでは)本来期待するようには行われなかったという事だと思ってます。
</p>
<p>
そもそも、replicate-wild-ignore-table の使い方というか、使ってよい条件を満たせていなかったのかもしれません。元々、滅多に使わないテーブルに関する設定だったので、これで収まるならそれはそれでよいかな、といった所です。
</p>
<p>
本当に解決していたらうれしい限りです。
</p>]]>
        
    </content>
</entry>

<entry>
    <title>MySQL のレプリケーションで保存時のキャラクタセットが変わる問題</title>
    <link rel="alternate" type="text/html" href="http://blog.koshigoe.jp/archives/2009/10/mysql_4.html" />
    <id>tag:blog.koshigoe.jp,2009://3.1287</id>

    <published>2009-10-24T15:08:33Z</published>
    <updated>2009-10-24T15:09:30Z</updated>

    <summary> 何が悪いのかよくわからない。 問題が発生したレコードのタイムスタンプとバイナリログを確認すると、replicate-wild-ignore-table でレプリケーション対象から外したテーブルへのクエリが実行された近辺だという事はわかりました。 また、バイナリログがローテーションされ、新しいバイナリログからレプリケーションする時には問題が解消されているらしき事もわかりました。 何かでスレーブサーバの SQL スレッドのキャラクタセットの設定がおかしくなり、バイナリログが変わって改めてキャラクタセットが設定されたために治ったのではなかろうかと疑っています。 問題発生の傾向が結構あからさまなので、その問題発生近辺のバイナリログをみれば、何が起きているのかすぐわかるかと思った訳ですが、いまいちよくわかりません。 ひとまず、「問題発生の傾向が結構あからさま」という事がわかっただけでも前進でしょうか。完全に不規則だったら、自分にはお手上げでした。 まずは replicate-wild-ignore-table をやめてみて、それでだめなら必要そうなログを記録して、再検討かなと思っています。 ...</summary>
    <author>
        <name>koshigoe</name>
        <uri>http://blog.koshigoe.jp/</uri>
    </author>
    
        <category term="tech" scheme="http://www.sixapart.com/ns/types#category" />
    
    <category term="mysql" label="mysql" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="ja" xml:base="http://blog.koshigoe.jp/">
        <![CDATA[<p>
何が悪いのかよくわからない。
</p>
<p>
問題が発生したレコードのタイムスタンプとバイナリログを確認すると、replicate-wild-ignore-table でレプリケーション対象から外したテーブルへのクエリが実行された近辺だという事はわかりました。
</p>
<p>
また、バイナリログがローテーションされ、新しいバイナリログからレプリケーションする時には問題が解消されているらしき事もわかりました。
</p>
<p>
何かでスレーブサーバの SQL スレッドのキャラクタセットの設定がおかしくなり、バイナリログが変わって改めてキャラクタセットが設定されたために治ったのではなかろうかと疑っています。
</p>
<p>
問題発生の傾向が結構あからさまなので、その問題発生近辺のバイナリログをみれば、何が起きているのかすぐわかるかと思った訳ですが、いまいちよくわかりません。
</p>
<p>
ひとまず、「問題発生の傾向が結構あからさま」という事がわかっただけでも前進でしょうか。完全に不規則だったら、自分にはお手上げでした。
</p>
<p>
まずは replicate-wild-ignore-table をやめてみて、それでだめなら必要そうなログを記録して、再検討かなと思っています。
</p>]]>
        
    </content>
</entry>

<entry>
    <title>Snow Leopard に MacPorts でインストールした Ruby が遅いという話を聞いたけど…</title>
    <link rel="alternate" type="text/html" href="http://blog.koshigoe.jp/archives/2009/10/snow_leopard_ma.html" />
    <id>tag:blog.koshigoe.jp,2009://3.1286</id>

    <published>2009-10-16T18:55:51Z</published>
    <updated>2009-10-16T18:57:59Z</updated>

    <summary><![CDATA[ 会社でそんな話を聞きましたが、自分の環境で全く気づかなかったのはなんでだろう？ Googole 経由で Leopard の頃の記事が見つかりました。 MacPorts でインストールした Ruby は遅いらしい - kwatchの日記 記事のテストを自分の環境でも試してみました。 # fib.rb def fib(n)   n &lt;= 1 ? 1 : fib(n-1) + fib(n-2) end if __FILE__ == $0   require 'benchmark'   n = $N ? $N.to_i : 30   Benchmark.benchmark do |x|     x.report("fib(#{n})") do       fib(n)     end   end end $ uname -a Darwin imac.local 10.0.0 Darwin Kernel Version 10.0.0: Fri Jul 31 22:46:25 PDT 2009; root:xnu-1456.1.25~1/RELEASE_X86_64 x86_64 $ port installed...]]></summary>
    <author>
        <name>koshigoe</name>
        <uri>http://blog.koshigoe.jp/</uri>
    </author>
    
        <category term="tech" scheme="http://www.sixapart.com/ns/types#category" />
    
    <category term="ruby" label="ruby" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="ja" xml:base="http://blog.koshigoe.jp/">
        <![CDATA[<p>
会社でそんな話を聞きましたが、自分の環境で全く気づかなかったのはなんでだろう？
</p>
<p>
Googole 経由で Leopard の頃の記事が見つかりました。<br />
<a href="http://d.hatena.ne.jp/kwatch/20081117/1226936123">MacPorts でインストールした Ruby は遅いらしい - kwatchの日記</a>
</p>
<p>
記事のテストを自分の環境でも試してみました。
</p>
<pre>
# fib.rb
def fib(n)
  n &lt;= 1 ? 1 : fib(n-1) + fib(n-2)
end

if __FILE__ == $0
  require 'benchmark'
  n = $N ? $N.to_i : 30
  Benchmark.benchmark do |x|
    x.report("fib(#{n})") do
      fib(n)
    end
  end
end
</pre>
<pre>
$ uname -a
Darwin imac.local 10.0.0 Darwin Kernel Version 10.0.0: Fri Jul 31 22:46:25 PDT 2009; root:xnu-1456.1.25~1/RELEASE_X86_64 x86_64
$ port installed ruby
The following ports are currently installed:
  ruby @1.8.7-p174_0+darwin+thread_hooks (active)
$ /usr/bin/ruby -v -s fib.rb -N=33
ruby 1.8.7 (2008-08-11 patchlevel 72) [universal-darwin10.0]
fib(33)  4.680000   0.010000   4.690000 (  5.324309)
$ /usr/local/bin/ruby -v -s fib.rb -N=33
ruby 1.8.7 (2009-06-12 patchlevel 174) [i686-darwin10.0.0], MBARI 0x6770, Ruby Enterprise Edition 20090928
fib(33)  3.970000   0.010000   3.980000 (  4.786717)
$ /opt/local/bin/ruby -v -s fib.rb -N=33
ruby 1.8.7 (2009-06-12 patchlevel 174) [i686-darwin10]
fib(33)  4.790000   0.010000   4.800000 (  5.772489)
</pre>
<p>
とりあえず、参考記事ほどの差はありませんでした。
</p>
<p>
後は、Ruby Benchmark Suite を実行してみようと思いますが、結構な時間がかかる様なのでここまで。
</p>]]>
        
    </content>
</entry>

<entry>
    <title>派手に Class.new(ActiveRecord::Base) しまくってメモリ大量消費</title>
    <link rel="alternate" type="text/html" href="http://blog.koshigoe.jp/archives/2009/10/_classnewactive.html" />
    <id>tag:blog.koshigoe.jp,2009://3.1285</id>

    <published>2009-10-13T15:20:34Z</published>
    <updated>2009-10-13T15:22:37Z</updated>

    <summary> テーブル名を実行時に取得しなければならないために、実行時にモデルクラスを生成してたら、無遠慮に Class.new してて失敗した件。 細かく説明しませんが、ユーザごとにテーブル定義を決定する様な仕組みを、以下のページでサンプルとして書いたように Class.new(ActiveRecord::Base) して実装していました。 KoshigoeBLOG: メタクラスってなんなんだすか？(1) その発想(?)自体は別にどうという事でもありませんが、毎回 object_id の異なる同名クラスを作成してしまって問題を引き起こしていた事に気がつきました。何が問題かというと、永続的なプロセスの中で、何度も ActiveRecord::Base を継承した同名テーブルの(object_id の異なる)モデルクラスを作成してしまうと、GC されずにメモリに積み上がっていくという事です。 以下のコードの通り、ActiveRecord::Base を継承する度に、ActiveRecord::Base の @@subclasses[] に派生クラスが登録される様です。 module ActiveRecord   ...  ...</summary>
    <author>
        <name>koshigoe</name>
        <uri>http://blog.koshigoe.jp/</uri>
    </author>
    
        <category term="tech" scheme="http://www.sixapart.com/ns/types#category" />
    
    <category term="rails" label="rails" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="ruby" label="ruby" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="ja" xml:base="http://blog.koshigoe.jp/">
        <![CDATA[<p>
テーブル名を実行時に取得しなければならないために、実行時にモデルクラスを生成してたら、無遠慮に Class.new してて失敗した件。
</p>
<p>
細かく説明しませんが、ユーザごとにテーブル定義を決定する様な仕組みを、以下のページでサンプルとして書いたように Class.new(ActiveRecord::Base) して実装していました。<br />
<a href="http://blog.koshigoe.jp/archives/2008/09/1.html">KoshigoeBLOG: メタクラスってなんなんだすか？(1)</a>
</p>
<p>
その発想(?)自体は別にどうという事でもありませんが、毎回 object_id の異なる同名クラスを作成してしまって問題を引き起こしていた事に気がつきました。何が問題かというと、永続的なプロセスの中で、何度も ActiveRecord::Base を継承した同名テーブルの(object_id の異なる)モデルクラスを作成してしまうと、GC されずにメモリに積み上がっていくという事です。
</p>
<p>
以下のコードの通り、ActiveRecord::Base を継承する度に、ActiveRecord::Base の @@subclasses[] に派生クラスが登録される様です。
</p>
<pre>
module ActiveRecord
  ...
  class Base
    ...
    def self.inherited(child) #:nodoc:
      @@subclasses[self] ||= []
      @@subclasses[self] << child
      super
    end
    ...
end
</pre>
<p>
未だ Rails の事をよくわかっていないのでこれ以上は(少なくとも今は)書きませんが、今までだいぶ浮かれポンチな事をしていたな、と。
</p>
<p>
でも、すっきりして一安心です。
</p>]]>
        
    </content>
</entry>

</feed>
