<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/rss2japanesefull.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" version="2.0" xml:lang="ja">
<channel>
<title>coﾘ・ー・ﾝ＜2nd life</title>
<link>http://d.hatena.ne.jp/secondlife/</link>
<description>coﾘ・ー・ﾝ＜2nd life</description>
<dc:creator>secondlife</dc:creator>


<atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/rss+xml" href="http://feeds.feedburner.com/jp/secondlife" /><feedburner:info uri="jp/secondlife" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><item>
<title> fluentd を使った大規模ウェブサービスのロギング</title>
<link>http://feedproxy.google.com/~r/jp/secondlife/~3/3wSiYeXBRNg/1331094643</link>

<description><![CDATA[
<div class="section">
<p>先月行われた <a href="http://www.zusaar.com/event/193104">Fluentd meetup in Japan</a>というイベントで発表してきました！一ヶ月前だけどエントリーにするの忘れていたので、今更ながらエントリーに。</p>
<p><div style="width:425px" id="__ss_11412913"> <strong style="display:block;margin:12px 0 4px"><a target="_blank" href="http://www.slideshare.net/hotchpotch/20120204fluent-logging" title="fluentd を利用した大規模ウェブサービスのロギング">fluentd を利用した大規模ウェブサービスのロギング</a></strong> <iframe src="http://www.slideshare.net/slideshow/embed_code/11412913" width="425" height="355" frameborder="0" marginwidth="0" marginheight="0" scrolling="no"></iframe> <div style="padding:5px 0 12px"> View more <a target="_blank" href="http://www.slideshare.net/">presentations</a> from <a target="_blank" href="http://www.slideshare.net/hotchpotch">hotchpotch</a> </div> </div></p>
<p>fluentd、クックパッドではすでに100台以上のサーバに入れて各種ログを集約してますが本当に便利で。あとログ以外も最近 fluentd 経由で投げ始めたので、その辺も近々エントリーにできたらなーと思います。</p>
</div>
]]></description>

<dc:creator>secondlife</dc:creator>

<pubDate>Wed, 07 Mar 2012 04:30:43 GMT</pubDate>




<feedburner:origLink>http://d.hatena.ne.jp/secondlife/20120307/1331094643</feedburner:origLink></item>

<item>
<title> プログラミングの楽しさ。オープンソースとの出会い。</title>
<link>http://feedproxy.google.com/~r/jp/secondlife/~3/X-avTO8dnIs/1328168076</link>

<description><![CDATA[
<div class="section">

<ul>
<li> <a href="http://codezine.jp/article/detail/6401">100人のプロが選んだソフトウェア開発の名著　君のために選んだ1冊</a></li>
</ul>
<p>が出版され、『私と <a href="http://subtech.g.hatena.ne.jp/keyword/Ruby" class="okeyword">Ruby</a> と添削と』という内容で寄稿しました。私がどうプログラミング・オープンソースの楽しさを知ったかについての昔話です。公開して良い、とのことなので公開いたします。</p>
<p>なお、文章中に出てくる tdiarytimes.rb のコードは以下です。9年前に書いたコードなので今読み返すと恥ずかしいを通り越してもはや微笑ましいですね！！１これでも当時は、自分なりにできるだけ綺麗なコードにして公開した記憶があります。</p>

<ul>
<li> <a href="https://github.com/tdiary/tdiary-contrib/blob/master/plugin/tdiarytimes.rb">https://github.com/tdiary/tdiary-contrib/blob/master/plugin/tdiarytimes.rb</a></li>
</ul>
<br>

<h4> 私と <a href="http://subtech.g.hatena.ne.jp/keyword/Ruby" class="okeyword">Ruby</a> と添削と</h4>
<p>プログラミング技術の向上させるには、どういう方法があるでしょうか。プログラミングに関する書籍を読む、オープンソースで公開されているコードを読む、優秀な同僚と働くうちにテクニックが身についてくる、などなど様々な方法があるでしょう。</p>
<p>昔話をしましょう。私がプログラミングの楽しさを知り、プログラミングにのめり込んでいったのは大学三年生の時でした。当時プログラミングがあまり好きで無く、ほとんどコードをかけなかった私は、大学の研究室でコードを書く必要に迫られなんらかの方法でプログラミングを習得する必要がありました。</p>
<p>しかしながら、漠然とプログラミングを覚えようと思ってもすっと習得できるわけではありません。大学で習うプログラミングの話は、UML モデリングやオプジェクト思考の考え方で、アニマルクラスを継承して犬や猫が、といった概念的な話であったりしたため、そもそもプログラミングがよく解らない私にとってそのような高級なレイヤーの話はさっぱりでした。</p>
<p>そこで自分が作りたいものから作ってみようと思い、自分が使っていた日記システムに機能を増やしてみよう、と考えました。幸いにも使っていた日記システムが、プラグインで拡張可能な <a href="http://subtech.g.hatena.ne.jp/keyword/Ruby" class="okeyword">Ruby</a> で書かれた日記『tDiary』であったため、そのプラグインを試行錯誤しながら書いてみました。</p>
<p>実際に書いてみると、常日頃から使っているものが自分が手を加えることにより変化する、という何かを創造しているような万能感が楽しく、みるみるうちにプログラミングに嵌まっていきました。</p>
<p>なお当時(2003年) 周りでは <a href="http://subtech.g.hatena.ne.jp/keyword/php" class="okeyword">php</a> や <a href="http://subtech.g.hatena.ne.jp/keyword/Java" class="okeyword">Java</a> が流行っていましたが、周りと違ったことをしたいと思っていた自分は、当時ではまだまだマイナーだった <a href="http://subtech.g.hatena.ne.jp/keyword/Ruby" class="okeyword">Ruby</a> を書ける自分カッコイイ的な中二病的な感覚に酔いしれたいと思って居たのも良い思い出です。</p>
<p>そんなプログラミングの楽しさが徐々に解ってきたときに、MTBlogTimes という投稿した時間帯によってバーコードのような画像にラインを刻む(画像検索するとどんなものかすぐ解ると思います) Movable Type のプラグインがシンプルでかっこよかったため、それを tDiary のプラグインとして実装した tdiarytimes.rb というライブラリを公開したところ、tDiary 作者のただただしさんの目にとまり、tDiary の CVS レポジトリの中に入れてもらえました。</p>
<p>自分が作ったものが本家のコードに入るなんて！と大変喜んだのですがそれだけではありませんでした。本稿で推薦している本の作者、青木峰郎さんが tdiarytimes.rb をクラス分けし継承し、クラスごとに画像の見せ方を変え、オブジェクト思考の実装を入れ、大幅にリファクタリングしてくださったのです。このリファクタリングにより、クラスの使い方、継承の概念、よりシンプルなコードの書き方など様々なプログラミングのエッセンスを学ぶことができました。</p>
<p>またオープンソースでコードを公開することのメリットや楽しさも知ることができ、外に出すのも恥ずかしいようなコードでもとりあえず公開しておくと、自分にとっても役立つし、誰かのためにもひょっとしたら役に立つかも、と思うようになりどんどんコードを公開するようになりました。</p>
<p>その後、別のイベントで青木さんにまたコードを添削していただく機会に恵まれました。昔よりはプログラミングができるようになったけど、いまいちどこを改善して良いのか解らないと思っていたいましたが、様々な箇所に指摘をもらい、またプログラミングのテクニックを学ぶことができました。</p>
<p>「Rubyist Magazine 出張版 正しい<a href="http://subtech.g.hatena.ne.jp/keyword/Ruby" class="okeyword">Ruby</a>コードの書き方講座」では、私のコード改善も含めた系6本の具体的なリファクタリング手法が載っています。実践的な内容になっており、実際のライブラリをどう改善するかというのがストーリーとして書かれており、読み物としても面白いです。リファクタリングのポイントも「コーディングスタイル」「プログラミング一般」「<a href="http://subtech.g.hatena.ne.jp/keyword/Ruby" class="okeyword">Ruby</a>プログラミング一般」「オブジェクト指向プログラミング」「リフレクション(<a href="http://subtech.g.hatena.ne.jp/keyword/Ruby" class="okeyword">Ruby</a> では今ではメタプログラミングという表記が一般的でしょうか)」と様々な視点が書かれており、<a href="http://subtech.g.hatena.ne.jp/keyword/Ruby" class="okeyword">Ruby</a> のみならず標準的なプログラミングの考え方についても解説されています。</p>
<p>また、優秀なプログラマはそれぞれ、ポリシーを持ってコード書いており、たとえば空白スペースやインデント、メソッド名のつけ方一つとっても「なんでそのようなコードになってるか」一つ一つ説明できるような意味を持ってつけています。私が尊敬しているプログラマの一人である青木さんが、どんなポリシーを持ってコードを書いているかも解説されているのも嬉しいですね。</p>
<p>コードが書けるようになったは良いけど、どうやったらより良いコードになるか解らない、そんなプログラミング初心者は手にとって読んでみると、新しい発見があると思います。また本の内容も難しくなく「リファクタリングの本を読んでみたけど、正直よく解らなかった…」という方も読んでみてはいかがでしょうか。本自体は今風ではないですが、プログラミングのエッセンスは十分生かせる内容となっています。</p>
<p>プログラミング技術を向上させるには様々な方法があります。自分の場合は書籍を読んだり公開されているコードを読んだ時にも確かに技術や考え方は向上したと思うのですが、何よりも確実に向上したと思えたのが誰かに「添削」されたときでした。青木さんの添削もそうですし、同僚からのコードレビューもそうでしたし、オープンソースで公開したコードがリファクタリングされたときもそうでした。</p>
<p>今現在は当時とは違い、github を中心としたコミニュティベースでのソースコードの公開、添削、改善のサイクルが生まれています。あなたの公開したコードが昔よりもさらにより誰かが改善してくれやすい環境になっているでしょう。書いたコードが手元で眠っているなら、それをパブリックな場所で公開してみてはどうでしょうか。そのコードを添削してくれる誰かが現れ、よりあなたのプログラミング技術が向上するかもしれませんよ。</p>
<p>ちなみに本稿の話に出てきた tdiarytimes.rb、青木さんがリファクタリングされた tdiarytimes2.rb は現在も tDiary の git レポジトリに入っており、github 等から取得することができます。今見返したら tdiaritymes.rb はメソッドでもなんでもない箇所に、ベタで70行以上もコードが書いてあり歴史を感じることができました…。</p>
</div>
]]></description>

<dc:creator>secondlife</dc:creator>

<pubDate>Thu, 02 Feb 2012 07:34:36 GMT</pubDate>




<feedburner:origLink>http://d.hatena.ne.jp/secondlife/20120202/1328168076</feedburner:origLink></item>

<item>
<title> 例えば GC を止める・Ruby ウェブアプリケーションの高速化</title>
<link>http://feedproxy.google.com/~r/jp/secondlife/~3/GOEHWnYJNcY/1317893282</link>

<description><![CDATA[
<div class="section">
<p>最近クックパッドでは、アプリケーションサーバの大半が Rails 2.3 から Rails 3 に置き換わったのですが<span class="footnote"><a href="/secondlife/#f1" name="fn1" title="Rails 2.3 -&#62; 3 移行はクックパッド規模になるとかなり大変でしたが、いろいろな面白いアプローチを試せたので、これはこれで何処かでお話ししたいですね">*1</a></span>、リリース前のベンチマークの時点ではあまりパフォーマンスが出ず四苦八苦していました。具体的には Rails 2.3 の時と比べ MRI 1.8.7 だとレスポンスタムが200%ぐらい遅い結果でした。Rails 3 になって実装が Merb core を取り入れ疎結合で綺麗になった反面、より多くのオブジェクトと・メモリを利用する様になった影響かと思います。</p><p>そこで <a href="http://subtech.g.hatena.ne.jp/keyword/Ruby" class="okeyword">Ruby</a> インタプリタの変更<span class="footnote"><a href="/secondlife/#f2" name="fn2" title=" Ruby 1.9.2 化も考えましたが、テスト通すまでまただいぶ時間がかかる＆いっぺんにやると問題切り分けが難しいので一緒にアップグレードすることは見送りました ">*2</a></span>を行い検証をしたところ</p>

<ul>
<li> MRI 1.8.7

<ul>
<li> (Rails 2.3と比べ) 約200%遅い</li>
</ul>
</li>
<li> MRI 1.8.7 -&#62; <a href="http://subtech.g.hatena.ne.jp/keyword/Ruby" class="okeyword">Ruby</a> Enterprise Edition 1.8.7 2011.03 (tcmalloc 無効)

<ul>
<li> 約180%低速</li>
</ul>
</li>
<li> MRI 1.8.7 -&#62; <a href="http://subtech.g.hatena.ne.jp/keyword/Ruby" class="okeyword">Ruby</a> Enterprise Edition 1.8.7 2011.03 (tcmalloc 有効)

<ul>
<li> 約140%低速</li>
</ul>
</li>
</ul>
<p>のような感じで、無視できないほど速度が遅く、これではリリースが危ぶまれました。なお、どこで速度が遅いのかというと、GC の実行でだいぶ時間を使っていました。Rails3 でオブジェクトが増えたため、より GC の実行時間がかかる様になってしまったようです。</p>
<h4> Unicorn の導入</h4>
<p>次にアプリケーションサーバを Apache + Passenger の組み合わせから Nginx + Unicorn の組み合わせに変更しました。Unicorn について簡単に説明すると、Rack 環境をロードした master プロセスが fork して子の worker を作るため、以下の様な特性を持ちます。</p>

<ul>
<li> fork による worker 生成のため、子 worker の起動が高速

<ul>
<li> そのため再起動が高速になり、再起動時のサーバ負荷が少ない</li>
<li> ただユーザからの処理を捌かない master プロセスが必ず存在するため、メモリ使用量が1プロセス分増える</li>
</ul>
</li>
<li> epoll / libev 等のイベントでうまく複数接続を捌くモデルでなく、worker 1プロセス1接続のため安定性が向上する

<ul>
<li> そのため、大量のコネクションを要求する必要なウェブサービスには向かない</li>
</ul>
</li>
</ul>
<p>Unicorn の特徴について、より詳しくは以下のエントリーで述べられてます。</p>

<ul>
<li> <a href="http://d.hatena.ne.jp/tkng/20100707/1278517873"> UnicornでSinatraアプリをデプロイしてみた - 射撃しつつ前転</a></li>
</ul><p>実際に Apache + Passenger の組み合わせから Nginx + Unicorn の組み合わせにすると、わずかにスループットが上がるなあ、といった感じで大きなパフォーマンス改善は見られませんでした。これは Unicorn の特性が高速化よりも安定性や再起動時のメリット<span class="footnote"><a href="/secondlife/#f3" name="fn3" title=" graceful な再起動がほとんどエラーや負荷無く行える重要性は、ウェブサービスを運用してる方なら解ると思います ">*3</a></span>、シグナルを送るだけで操作できるシンプルさに重みが置かれてるからで、Rack というインターフェイスを通して操作される <a href="http://subtech.g.hatena.ne.jp/keyword/Ruby" class="okeyword">Ruby</a> アプリケーションの直接的な速度にはあまり関わってこないことを考えても納得の結果でした。</p>
<h4> 明示的な GC.start</h4>
<p>しかし Unicorn について調べている途中、<a href="http://unicorn.bogomips.org/TUNING.html">Tuning Unicorn</a> で <a href="http://unicorn.bogomips.org/Unicorn/OobGC.html">Unicorn::OobGC</a> という面白いアプローチを見つけました。</p>
<p>これは指定のリクエスト回数アプリケーションが処理を終えたら、ユーザにコンテンツを返した後に明示的に GC.start するというアプローチです。何が良いのかというと、GC がユーザのリクエスト外で実行するため、リクエスト中の処理では GC が走りにくくなり、結果ユーザへのレスポンス返却速度が高速化されるというわけです。</p>
<p>これを適用したところ、140%ぐらい遅かった速度が 130%ほどへとわずかに高速化されました。たぶん小規模なアプリケーションだと効果が結構見込めそうなのですが、メモリをだいぶ食ってる大規模なアプリケーションだとこれを使っても GC が頻繁に実行され、結果あまり速くならないようでした。</p>
<h4> GC を止める</h4>
<p>ここでいっそ GC.disable でユーザからのリクエスト処理中は GC を止めてしまい、リクエスト外で GC をしたらどうなるか、と思いついたので試してみました。</p>
<p>Unicorn は worker が master から fork される特徴があり、fork した直後のプロセスに対して設定で処理を書けるので、unicorn.conf.rb の設定に</p>
<pre class="syntax-highlight">
after_fork <span class="synStatement">do</span> |<span class="synIdentifier">server, worker</span>|
  <span class="synIdentifier">GC</span>.disable <span class="synStatement">if</span> <span class="synIdentifier">RAILS_ENV</span> == <span class="synSpecial">'</span><span class="synConstant">production</span><span class="synSpecial">'</span>
</pre>

<p>の、GC.disable で GC が走らない様にする処理を入れ、OobGC のコードを GC.disable 時にも GC.start を実行できる様に変更し、その後再度 GC.disable で止める処理を入れました。</p>

<ul>
<li> <a href="https://github.com/defunkt/unicorn/commit/c7ba76a21c5d00fb5c173cd6aa847442bbc652cb">https://github.com/defunkt/unicorn/commit/c7ba76a21c5d00fb5c173cd6aa847442bbc652cb</a>

<ul>
<li> unicorn の master ブランチに入ってるので、次のリリース(バージョン 4.1.2 ?) には取り込まれると思います</li>
</ul>
</li>
</ul>
<p>この GC.disable のベンチマークを結果は以下です。</p>
<p><a href="http://f.hatena.ne.jp/secondlife/20111006173812" class="hatena-fotolife"><img src="http://cdn-ak.f.st-hatena.com/images/fotolife/s/secondlife/20111006/20111006173812.png" alt="f:id:secondlife:20111006173812p:image" title="f:id:secondlife:20111006173812p:image" class="hatena-fotolife"></a></p>
<p>赤のグラフが GC.disable しなかったサーバで、青のグラフが GC.disable するサーバです。あからさまに GC をユーザからのリクエスト処理中は無効化した方が断然高速な結果に終わりました。Rails 2.3 のサーバと比べても65%遅い、もとい150%ほど高速な結果となりました！！</p>
<h4> GC を止める Production のアプリケーションサーバに適用</h4><p>というわけで、このユーザのリクエスト処理中は GC を無効化する方法でだいぶ高速化することが解ったので、一足先に Unicorn 化していた Rails 2.3 サーバ(<a href="http://subtech.g.hatena.ne.jp/keyword/Ruby" class="okeyword">Ruby</a> のバージョンは MRI 1.8.7 で <a href="http://subtech.g.hatena.ne.jp/keyword/Ruby" class="okeyword">Ruby</a> Enterprise ではない)に適用したところ、それだけで 130% ほど高速化 & CPU 消費量が減る <span class="footnote"><a href="/secondlife/#f4" name="fn4" title=" CPU 使用率はあまり変わらないと思ってたんですが大きく減ったのが不思議な感じです… ">*4</a></span> という素晴らしい結果になりました。</p>
<p><a href="http://f.hatena.ne.jp/secondlife/20111003181720" class="hatena-fotolife"><img src="http://cdn-ak.f.st-hatena.com/images/fotolife/s/secondlife/20111003/20111003181720.png" alt="f:id:secondlife:20111003181720p:image" title="f:id:secondlife:20111003181720p:image" class="hatena-fotolife"></a></p>
<p><a href="http://f.hatena.ne.jp/secondlife/20111003181721" class="hatena-fotolife"><img src="http://cdn-ak.f.st-hatena.com/images/fotolife/s/secondlife/20111003/20111003181721.png" alt="f:id:secondlife:20111003181721p:image" title="f:id:secondlife:20111003181721p:image" class="hatena-fotolife"></a></p>
<p>なお Rails3 ほど顕著に高速化しなかったのは、Rails3 にくらべメモリ使用量が少ないからかと思います。その後 Rails3 に刷新後は当初の Unicorn 化する以前の Rails 2.3 アプリに比べ、最終的に 150% ほど高速化しました。</p>
<h4> まとめ</h4>
<p>Web アプリケーションの速度の高速化は、IO 処理の高速化を除いてしまうと、チューニングすればするほど大きく改善する方法はなくなっていくと思ってましたが、ユーザのレスポンス処理中は GC を止め、その外で実行するだけで大きくパフォーマンスが改善しました。<a href="http://subtech.g.hatena.ne.jp/keyword/Ruby" class="okeyword">Ruby</a> 1.8 系統を使ってるサービスは試してみる価値があると思います。</p>
<p>なお今後リリースされる予定の <a href="http://subtech.g.hatena.ne.jp/keyword/Ruby" class="okeyword">Ruby</a> 1.9.3 では nari3 が実装された Lazy Sweep GC が載るので、OobGC 的な事を <a href="http://subtech.g.hatena.ne.jp/keyword/Ruby" class="okeyword">Ruby</a> 自体が行ってくれ、GC の最大実行時間が減ると思うので、<a href="http://subtech.g.hatena.ne.jp/keyword/Ruby" class="okeyword">Ruby</a> 1.9 なサービスは 1.9.3 に変えるだけでパフォーマンス改善がされそうですね。</p>

<ul>
<li> <a href="http://www.infoq.com/jp/news/2011/08/ruby193-gc">InfoQ: Ruby 1.9.3 Preview 1がリリース。Lazy Sweep GCにより、GCの停止時間が改善。</a></li>
</ul>
<h4> おまけ・運用ノウハウなど</h4>
<h5> メモリリークの対応</h5>
<p>GC.disable している期間が長いと、GC.start したときに元のコードがメモリリークしてると、よりそのメモリーを解放できない様な感じで、どんどん Rails アプリケーションのプロセスサイズが肥大化して行ってしまいました。</p>
<p>Unicorn は worker プロセスに SIGQUIT を送ると、ユーザのリクエスト処理が終わった直後にプロセスが死んで、master プロセスがそれを検知してすぐに fork する仕組みがあるので、以下のユーティリティを書いて Rack レイヤーで対応しました。</p>

<ul>
<li> <a href="https://gist.github.com/1258681">https://gist.github.com/1258681</a></li>
</ul>
<pre class="syntax-highlight">
use <span class="synIdentifier">UnicornKiller</span>::<span class="synIdentifier">Oom</span>, <span class="synConstant">400</span> * <span class="synConstant">1024</span> <span class="synComment"># 使用メモリが400Mを超えると自分自身に SIGQUIT</span>
use <span class="synIdentifier">UnicornKiller</span>::<span class="synIdentifier">MaxRequests</span>, <span class="synConstant">1000</span> <span class="synComment"># 1000 回リクエストを超えると自分自身に SIGQUIT</span>
</pre>

<p>プロセスを終了しても即座に fork で新しい worker が作られるため、こんな感じのざっくりとした対応でも問題無く運用できてます。</p>
<h5>Unicorn + bundler でのデプロイ時の問題</h5>
<p>突然はまるのでちゅうい…。特に Unicorn は master プロセスへの SIGUSR2 (graceful な再起動)で再起動に失敗した場合、何事もなかったのように昔のプロセスは正常に生き続けるため、ぱっと見問題に気づきません…。</p>

<ul>
<li> <a href="http://blog.twiwt.org/e/2e6270">Twiwt:Blog / jugyo : Capistrano によるデプロイ時に Unicorn の再起動に失敗することがある問題への対処</a></li>
<li> <a href="https://willj.net/2011/08/02/fixing-the-gemfile-not-found-bundlergemfilenotfound-error/">no title</a></li>
</ul>
<h5>アプリケーションサーバのベンチマークとパラメータの調整</h5>
<p>ベンチマークには最初 ab (apache bench) でいくつかの URL でベンチ、次に JMeter で本番リクエストの上位80%のリクエストをエミュレートしてベンチをとりました。環境さえ作ればあとは叩くだけなので、ab / JMeter を使いつつ、アプリケーションサーバのメモリー数、CPU の利用状況を見て Unicorn のプロセス数の調整と <a href="http://subtech.g.hatena.ne.jp/keyword/Ruby" class="okeyword">Ruby</a> Enterprise Edition の GC 周りの環境変数を調整しました。</p>
<p>この辺はサービスごとに最適値が違うと思うので、ちまちま数字変えてやるのが良いと思います。</p>
</div>
<div class="footnote">
<p class="footnote"><a href="/secondlife/#fn1" name="f1">*1</a>：Rails 2.3 -&#62; 3 移行はクックパッド規模になるとかなり大変でしたが、いろいろな面白いアプローチを試せたので、これはこれで何処かでお話ししたいですね</p>
<p class="footnote"><a href="/secondlife/#fn2" name="f2">*2</a>： <a href="http://subtech.g.hatena.ne.jp/keyword/Ruby" class="okeyword">Ruby</a> 1.9.2 化も考えましたが、テスト通すまでまただいぶ時間がかかる＆いっぺんにやると問題切り分けが難しいので一緒にアップグレードすることは見送りました </p>
<p class="footnote"><a href="/secondlife/#fn3" name="f3">*3</a>： graceful な再起動がほとんどエラーや負荷無く行える重要性は、ウェブサービスを運用してる方なら解ると思います </p>
<p class="footnote"><a href="/secondlife/#fn4" name="f4">*4</a>： CPU 使用率はあまり変わらないと思ってたんですが大きく減ったのが不思議な感じです… </p>
</div>
]]></description>

<dc:creator>secondlife</dc:creator>

<pubDate>Thu, 06 Oct 2011 09:28:02 GMT</pubDate>




<feedburner:origLink>http://d.hatena.ne.jp/secondlife/20111006/1317893282</feedburner:origLink></item>

<item>
<title> さいきんの Rails サービスを高速化をしてみた</title>
<link>http://feedproxy.google.com/~r/jp/secondlife/~3/yJ4gVFx6OlY/1316438465</link>

<description><![CDATA[
<div class="section">
<p>先日のももクロハッカソンで出会った wantedly を作ってる仲さんが</p>
<p><a href="http://wantedly.com/jobs/977"><img src="http://cache.gyazo.com/7b2ea7a4c04a050c50df6959ce26360c.png"></a></p>
<p>と言ってたので、面白そうなので wantedly を速くしてみました。</p>

<ul>
<li> <a href="http://wantedly.com/">wantedly</a></li>
</ul>
<p>ちなみにデータが数百万オーダーもなさそうなのに、どのページもログインすると2-5秒ぐらいかかっていたので、確実に速くできそうだなぁという感覚はやる前からありました。</p>
<h4> アプリケーションサイドのチューニング</h4><p>初心者<span class="footnote"><a href="/secondlife/#f1" name="fn1" title="仲さんはプログラミング初めて一年、Rails 初めて数ヶ月ですが、Ruby の実装から html / css / js ほぼすべて一人で wantedly 作ってすごい…">*1</a></span>にありがちな問題として</p>

<ul>
<li> SQL に適切にインデックス張ってない</li>
<li> キャッシュすべき場所をキャッシュしていない</li>
<li> 無駄なデータを引きすぎてる</li>
</ul>
<p>ことがよくあります。ので順に実装を見ていきました。</p>
<h5> SQLに適切なインデックスを張ってない</h5>
<p>張ってありました！びっくり！＼(^o^)／</p>
<h5> キャッシュすべき場所をキャッシュしていない</h5>
<p>Facebook API を利用したアプリケーションなんですが、ユーザのデータの取得を毎回馬鹿正直に HTTP を叩いてとっていたため、適切にキャッシュを入れました。これで1秒強ぐらい速くなりました。</p>
<h5> 無駄なデータを引きすぎている</h5><p>うっかり全件データ(!) を引いていたり、引かなくて良いデータを引いていたり箇所をログと New Relic <span class="footnote"><a href="/secondlife/#f2" name="fn2" title="Heroku 無料で New Relic プラグインが使えて便利">*2</a></span>から見ていって直していきました。これでログインユーザが1-3秒ぐらい速くなりました。</p>
<p>SQL のインデックス張ってない問題やこれの問題は、データが少ない当初は遅いと感じなくても、データが増えれば増えるほど徐々に重くなっていき、また開発環境でデータが少ないこともあるため、初心者には気づきにくい & どこを直したら良いか解らないといったことが発生しがちでしょう。</p>
<h5> 結果</h5>
<p>約6倍速＼(^o^)／</p>
<p><img src="http://cache.gyazo.com/6d7960c467c48a5fb8b8c440f8d8e09f.png"></p>
<h4> 体感速度のチューニング</h4>
<p>続いてユーザが実際に感じる速度を向上させました。</p>
<p>wantedly は heroku にあるためサーバが遠く、1ファイルの取得に 200ms-300ms のタイムラグが発生します。そのため、以下のアプローチをとりました。</p>
<br>

<h5> リダイレクトは極力減らす</h5>
<p>リダイレクトするとそれだけで200-300ms遅く感じてしまうため、よくクリックするリンクはリダイレクトで無く、URL の生成でちゃんとリダイレクト先を生成するように変更しました。</p>
<br>

<h5> 静的ファイルをまとめる</h5>
<p>Rails 3.1 からは 3.1 の目玉機能の一つ、asset pipeline が利用できるようになり、何も考えなくともルールに従えば js / css ファイルを一つにまとめられるようになったため、Rails 3.0 系から Rails 3.1.0 にアップグレードして asset pipeline を有効化しました。なお Rails 3.1.0 化はコード上 Rails 本体を弄る等無理な書き方をしてなかったため、割とすんなりアップグレードできました。</p>
<p>なお、heroku で asset pipeline をうまく使うには memcached plugin を入れ</p>
<pre>
# production.rb
  config.serve_static_assets = true
  config.assets.compress = true
  config.assets.compile = true
</pre>

<p>と設定するとうまく動くと思います。</p>
<h5> 静的ファイルをブラウザにキャッシュさせる</h5>
<p>いわゆる Expires / Cache-Control ヘッダの指定ですね。Rails 3.1 + Asset Pipipele + Heroku でうまくキャッシュさせるには</p>
<pre>
config.assets.digest = true
</pre>

<p>で asset の URL が内容が変更があったら変わるようにし(じゃないとキャッシュされ続けるため)</p>
<pre>
config.static_cache_control = &#34;public, max-age=#{1.day}&#34;
</pre>

<p>で、Rack の ActionDispatch::Static で Cache-Controle ヘッダをはかせるようにします。</p>
<br>

<h5>結果</h5>
<p>以前</p>
<p><img src="http://cache.gyazo.com/034114a69c805ac47f45d6c80b0a2bfd.png"></p>
<p>以後</p>
<p><img src="http://cache.gyazo.com/6b05fb4038f0c2f2da352f13279498c8.png"></p>
<p>ちょっとわかりにくいですが、青のラインが250msぐらい速くなり、体感的にもロードが速くなりました。特に Heroku のようなサーバが遠い場合は効果がだいぶ出ると思います。</p>
<h4>終わりに</h4>
<p>これ以上の高速化には国内のサーバにする & 動的では無いコンテンツにフロントでもう一段階ちゃんと Varnish 等を入れキャッシュ設計するが必要になりますが、それをするのはコストがかかりすぎるので、やるとしてもサービスがだいぶ伸びてからになると感じました。</p><p>あとよく Rails アプリ遅いと言われてますが、200ms 前後の速度でしたらサービスがだいぶ大きくならない限りは、Heroku 等の PaaS でも簡単に維持できるなぁと改めて感じました。<span class="footnote"><a href="/secondlife/#f3" name="fn3" title="200ms だと遅いという方も居ると思いますが、だいたい重いと感じるサービスはもっともっと処理コストがかかってると思うので…">*3</a></span></p>
<p>あとあと、初めてちゃんと Heroku 触ってみたんですがすごく良くできてますね。ただやっぱり太平洋超えるのは日本向けのサービスだとするとつらいなー、とも感じたので Heroku の ec2 の東京リージョン版が出たらより日本でも流行りそうですね〜。</p>
</div>
<div class="footnote">
<p class="footnote"><a href="/secondlife/#fn1" name="f1">*1</a>：仲さんはプログラミング初めて一年、Rails 初めて数ヶ月ですが、<a href="http://subtech.g.hatena.ne.jp/keyword/Ruby" class="okeyword">Ruby</a> の実装から html / css / js ほぼすべて一人で wantedly 作ってすごい…</p>
<p class="footnote"><a href="/secondlife/#fn2" name="f2">*2</a>：Heroku 無料で New Relic プラグインが使えて便利</p>
<p class="footnote"><a href="/secondlife/#fn3" name="f3">*3</a>：200ms だと遅いという方も居ると思いますが、だいたい重いと感じるサービスはもっともっと処理コストがかかってると思うので…</p>
</div>
]]></description>

<dc:creator>secondlife</dc:creator>

<pubDate>Mon, 19 Sep 2011 13:21:05 GMT</pubDate>




<feedburner:origLink>http://d.hatena.ne.jp/secondlife/20110919/1316438465</feedburner:origLink></item>

<item>
<title> 第一回ももクロハッカソンに参加して Acme::MomoiroClover リリースしました</title>
<link>http://feedproxy.google.com/~r/jp/secondlife/~3/e--iGjWhqR8/1315129581</link>

<description><![CDATA[
<div class="section">
<p>最近はかなこ推しになりつつある、週末エンジニアの secondlife ですこんにちは。</p>
<p>9/4(日)にももいろ週末エンジニアの方々と都内某所で、第一回ももクロハッカソンを開き参加し、<a href="http://subtech.g.hatena.ne.jp/keyword/Perl" class="okeyword">Perl</a> ライブラリの <a href="http://subtech.g.hatena.ne.jp/keyword/Acme" class="okeyword">Acme</a>::MomoiroClover を作りました。</p>

<ul>
<li> <a href="https://github.com/hotchpotch/perl-acme-momoiroclover">https://github.com/hotchpotch/perl-acme-momoiroclover</a> </li>
<li> <a href="http://search.cpan.org/~tateno/Acme-MomoiroClover/">http://search.cpan.org/~tateno/Acme-MomoiroClover/</a></li>
</ul>
<p>何故今更 <a href="http://subtech.g.hatena.ne.jp/keyword/Acme" class="okeyword">Acme</a>::MomoiroClover を作ったかと云うと、今までに日本のアイドルの <a href="http://subtech.g.hatena.ne.jp/keyword/Acme" class="okeyword">Acme</a> シリーズは二つ、<a href="http://subtech.g.hatena.ne.jp/keyword/Acme" class="okeyword">Acme</a>::MorningMusume と <a href="http://subtech.g.hatena.ne.jp/keyword/Acme" class="okeyword">Acme</a>::AKB48 があります。その <a href="http://subtech.g.hatena.ne.jp/keyword/Acme" class="okeyword">Acme</a> が存在するアイドル2ユニットに共通していえることの一つに、どちらも紅白歌合戦に参加したことがあることが言えます。つまるところ、日本の <a href="http://subtech.g.hatena.ne.jp/keyword/Acme" class="okeyword">Acme</a>::アイドル が作られたのユニットは100%紅白出場しているため、ももクロちゃんの今の目標である紅白歌合戦出場をほんの少しでもサポートできたらと思い、験担ぎの意味を込めて作りました！！</p>
<h4> 使い方</h4>
<p>至って簡単！</p>
<pre class="syntax-highlight">
<span class="synStatement">use </span>Acme::MomoiroClover;
<span class="synStatement">my</span> <span class="synIdentifier">$momoclo</span> = Acme::MomoiroClover-&#62;<span class="synStatement">new</span>;
</pre>

<p>とふつうに使おうとすると</p>
<pre>
MomoiroClover is obsolete. Please use Acme::MomoiroClover::Z 
</pre>

<p>となって使うことができません…。(マシンの時刻が2011年4月10日以前なら利用できます)</p>
<p>というわけで今は <a href="http://subtech.g.hatena.ne.jp/keyword/Acme" class="okeyword">Acme</a>::MomoiroClover::Z を使いましょう。</p>
<pre class="syntax-highlight">
<span class="synStatement">use </span>Acme::MomoiroClover::Z;
<span class="synStatement">my</span> <span class="synIdentifier">$momoclo_z</span> = Acme::MomoiroClover::Z-&#62;<span class="synStatement">new</span>;
</pre>
<p>API は <a href="http://subtech.g.hatena.ne.jp/keyword/Acme" class="okeyword">Acme</a>::MorningMusume とほぼ同じ<span class="footnote"><a href="/secondlife/#f1" name="fn1" title="ほぼ id:antipop さん作の Acme::MorningMusume のコピペモジュールなので…">*1</a></span>ですが、各 member に say メソッドがあり、自分のカラーで発言することができます<span class="footnote"><a href="/secondlife/#f2" name="fn2" title=" ピンクは端末が 256色対応じゃないと表現できないので明るい紫でごまかしております… ">*2</a></span>。</p>
<pre class="syntax-highlight">
<span class="synStatement">use </span>Acme::MomoiroClover::Z;

<span class="synStatement">my</span> <span class="synIdentifier">@members</span> = Acme::MomoiroClover::Z-&#62;<span class="synStatement">new</span>-&#62;members(<span class="synConstant">'active'</span>);
<span class="synStatement">my</span> <span class="synIdentifier">$count</span> = <span class="synConstant">0</span>;
<span class="synStatement">for</span> <span class="synStatement">my</span> <span class="synIdentifier">$member</span> (<span class="synIdentifier">@members</span>) {
  <span class="synIdentifier">$count</span> = <span class="synConstant">0</span> <span class="synStatement">if</span> (++<span class="synIdentifier">$count</span> &#62;= <span class="synStatement">scalar</span>(<span class="synIdentifier">@members</span>));
  <span class="synIdentifier">$member</span>-&#62;say(<span class="synIdentifier">$members</span>[<span class="synIdentifier">$count</span>]-&#62;nick-&#62;[<span class="synConstant">0</span>] . <span class="synConstant">&#34;〜&#34;</span>);
}

</pre>

<p><img src="http://gyazo.com/979a6efd7f6e76547456aaf989c78706.png"></p>
<h4> <a href="http://subtech.g.hatena.ne.jp/keyword/Acme" class="okeyword">Acme</a>::アイドル について</h4>
<p><a href="http://subtech.g.hatena.ne.jp/keyword/Acme" class="okeyword">Acme</a>::アイドルに新しい1ユニットを追加したわけですが、<a href="http://subtech.g.hatena.ne.jp/keyword/Acme" class="okeyword">Acme</a>::MorningMusume の作成者、<a href="http://d.hatena.ne.jp/antipop/">id:antipop</a> 御大にお言葉をいただきました。</p>
<blockquote>

<ul>
<li> 「本当に大好きな時期は、メンテナンスコストはどうってことないけど、メンバー変更の精神的ダメージがつらい」</li>
<li> 「YAMLなどでのクラス自動生成は邪道。一個一個メンバーのクラスファイルがないと愛がない」</li>
</ul>
</blockquote>
<p>とのことで、気を引き締めていきたいと思う所存であります。</p>
<h4> ももクロハッカソンの週末エンジニアたち</h4>
<p>BGM としてスピーカからももクロの曲を流しながら流しながら作業をしてたんですが、お気に入りの曲になるとみんな歌うたったりコール出したり踊ったりするのでノリノリで作業できて超楽しかったです！特にももクロちゃん自己紹介と怪盗少女の時はみんながみんなノリノリになって一体感あふれてわくわくすぎました、また開催したい！！１</p>
</div>
<div class="footnote">
<p class="footnote"><a href="/secondlife/#fn1" name="f1">*1</a>：ほぼ <a href="http://d.hatena.ne.jp/antipop/">id:antipop</a> さん作の <a href="http://subtech.g.hatena.ne.jp/keyword/Acme" class="okeyword">Acme</a>::MorningMusume のコピペモジュールなので…</p>
<p class="footnote"><a href="/secondlife/#fn2" name="f2">*2</a>： ピンクは端末が 256色対応じゃないと表現できないので明るい紫でごまかしております… </p>
</div>
]]></description>

<dc:creator>secondlife</dc:creator>

<pubDate>Sun, 04 Sep 2011 09:46:21 GMT</pubDate>




<feedburner:origLink>http://d.hatena.ne.jp/secondlife/20110904/1315129581</feedburner:origLink></item>

</channel>
</rss>

