coverallsをperlなprojectで使えるようにしてみた

先週末に開催された Perl QA Hackathon 2013 Satellite Tokyo に参加してきた。会場が所属先だったんですが、普段仕事してるところに perl mongerな方々がいる光景はちょっと面白かったw

Perl QA Hackathonということで、それぞれcartonやcapnmやminillaやTest周りのモジュールを色々と触っていたんだけど、自分は http://coveralls.io/ という、githubやtravisを使ってるprojectが、簡単にテストのカバレッジを記録できるサイトの perl版を作ってみたいと思っていたので、それに着手。最初はサービスそのものを作ろうかと思ってたんだけど、よく調べてみたらcoverallsにはAPIがあって、それを利用した3rd partyのpythonやnodeのライブラリがあった(後で調べたらPHP版もある模様)ので、perlもAPI叩きさえすれば動くんじゃね? ということで、Devel::CoverのReporterとして作ってみた。

https://github.com/kan/coveralls-perl

既に Devel::Cover::Report::Coveralls としてCPANにも公開済みなので、SYNOPSISとかSmart::Optionsの設定を見て使って戴ければ幸い。

うまく動くとSmart::Optionsの例のごとく表示されます

久々にHackathonに参加したけど、やっぱり集中してもりもりコード書くのは楽しい(まあ最近は仕事も概ねそういう状態なんだけどもw)。今月はちょっと予定が被っちゃって泣くなくキャンセルしたんだけど、来月はHachiouji.pmとhackathonに参加してみたいなあ。

Acme::PrettyCure 0.1

出ました。

https://metacpan.org/module/Acme::PrettyCure

このモジュールをCPANに上げて以来の目標だった「新シリーズ開始日の更新」を達成できて満足。例年、「まだ全員揃ってないし、揃ってから出そう」→「あれ、もう夏(秋)だ」というパターンだったので……。

ドキドキ!プリキュア対応以外にも、このバージョンからAny::Mooseを使うのをやめてMooを使うように。Any::MooseのPODに「もうオワコンだからMoo使えMoo(意訳)」って書いてあるの知らなかったよ……。Mooへの移行は殆ど手間なく完了。Roleとかもそのまま使える。自分がつまづいたのは

  • isaの指定が文字列(StrとかInt)からチェック用サブルーチンを渡すようになったこと
  • overrideが無くなったこと(MooのPODには「overrideとかsuperはbad ideaだった。arround使え」とある)

くらいかなあ。

プリキュアも10年目になることだし、今年はTODOになってる機能も全部実装して1.0を出して、YAPCでLTして顰蹙を買うのが大目標です。

Smart::Options 0.04

https://metacpan.org/module/Smart::Options

ちょっと間が空いてしまったんだけど、Smart::Optionsをアップデートした。今回から値のタイプチェックが出来るようになったので、Smart::Options::Declareがopts.pmと完全に同じことが出来るように(coerce周りの記述がちょっと変更にはなってるけど)。

タイプチェックは名前の通りオプション引数の値をチェックする仕組みなんだけど

のように、値の形式を強制したりも出来たりする。

coerceはMo(use|ose)を使ってる人には馴染みのあるアレ。Smart::Options::DeclareのPODにも例があるけど、バッチスクリプトとかで使う場合はPath::ClassとかTime::Pieceのインスタンスに変換するような使い方が便利。

どうぞご利用下さい。あとSmart::Optionsはこれで一通り自分の使いたい機能は載せたんだけど、こんな機能が欲しい等は随時募集中です(ぜひpull-reqも)。

家の環境をひと通り入れ替えた話

大部分が去年のうちに終っていた話でアレなんだけど、転職してしばらくして落ち着いたところで、家のMacと周辺環境を見直してみることにした。

というのも、会社に支給してもらったのが2012版のMacBookAir(SSD以外全部盛り仕様)なので、手持ちのMacBookAir.2011のほうが歴然と遅い……。それに外付けディスプレイやスピーカー類はかなり前から使い続けてたので飽きもきてたし……といったあたりを言い訳に、ちょっとずつ入れ替えていったら気がついてたら全部入れ替わってたよ(棒読み)。

会社支給のMacBookAirを常に持ち歩いてるので家用はMac miniに。CPUとメモリはMAXで。ストレージは迷ったけど、元々使ってる外付けHDDもあるので性能優先でSSD 256GBに。この外付けHDDは、AirMacExtremeに繋いでネットワークドライブにしてたんだけど、変なタイミングでオフラインになったりして、想定してる使い方(iTunes LibraryとTime Machine用)に向いてなかったので結局Mac miniに直接刺して使ってる。

で、折角MacMiniにしたので2560x1440で表示できるディスプレイをということでDELLのU2173HMを購入。Mac miniなんだし当然Thunderbolt Displayって手もあったんだけど、PS3のモニタとしても使いたかったので、DisplayPortかVGAまで一通り揃ってる(そして安い)こっちのほうが良かった。1枚で今までのデュアルディスプレイ的に画面を使えるので快適。最近のMac OSはMissionControlとかの作りのせいもあって物理的なデュアルディスプレイが使い辛くなってるので大画面一点作戦は悪くなかったと思ってる(そもそも机がそんなにデカくないので、ぶっちゃけ27インチのこれ1枚置くとギリギリです)。

さらに、折角光オーディオ出力できるようになったので、それを使えるスピーカーをということで(泥縄)ONKYOのアンプ内蔵スピーカーを購入。スピーカー自体が前のより良いやつになったので低音が響くようになったのが嬉しい。ノイズとかは前からそんなに気にならなかったけど、細かい音も聴こえるようになった気はする(が、気のせいだと思う)。ちなむと、退役した元スピーカーは同じく退役したAirMacExpressと一緒に寝室に持ち込んだので、iPod touchからAirPlayで寝る時に流せるようになった。

結論としてはモニターとスピーカーを買い替えるとライブBDが楽しいので皆もやるといいよ!

バイナリファイルの差分を作るzdeltaが便利

去年のネタになってしまうんですが、ある程度でかく、かつ都度更新され続けるファイルの転送量を削減したいなーということになって、ちょっとずつ更新されてるなら実は差分は小さいんじゃね?ということで、バイナリのdiffをとって転送先でpatchをあてる、みたいなことが出来ないかなーと調べてました。

バイナリ差分生成系で一番ポピュラーなのはxdeltaのようで実際yumやaptで簡単に入れられるし、プロジェクトとしても更新が続いててドキュメントも揃っててなかなか良さげ。一方で bsdiffとxdeltaを比較してみた という記事で紹介されている bsdiff というのもあって、Google Chromeのアップデートとかでも使われたりしている模様(chromeの差分アップデートでは更に逆アセンブルした結果を差分アップデートしたりとか変態的なことやってるようですが)。

比較してみると、確かに bsdiff の圧縮率は xdelta より遥かに高いんだけど、その分CPU負荷やメモリ消費も高く、更に差分生成時間が3倍くらいかかる。で、その比較は数十MBのファイルで試してたんだけど、実際には数百MB(1G超えることも)のファイルでも使いたかったので、そっちで試したら1時間経っても返ってこない(おそらく試験機のリソース使い果たした)。

こりゃbsdiffは今回のユースケースには合わないなーという結論が出つつ、でもxdeltaだと差分のサイズがイマイチ……ということでもうちょっと粘ってみたところ、bsdiffのサイトで公開されてる競合比較の表にあった zdelta というのを調べてみることに。

すると、(後述する若干の問題はあったものの) bsdiff には及ばないながら 差分のサイズは xdelta よりかなり小さい ( bsdiff と xdelta の真ん中ぐらい ) 上に、元ファイルがGBになっても処理時間が爆発したりせず、差分適用はほぼ一瞬という素晴らしい結果が。

そんなわけで採用することになったんですが、これを見て「ふーん、使ってみるか」と思った方へ諸注意。zdeltaのソース一式は上記リンクから取得できるんですが、そのまま使うと差分を適用するコマンド実行時にセグフォで死にます。なんじゃそりゃ……とひとしきり悩んだ挙句、こちらで公開されているpatchをあてると解消することが判明。さらに、差分を適用するコマンド(zdu)のusageが間違っていて、usageは「zdu source target patch」の順になってるんですが、「zdu source patch target」でないと動きません。手元ではusageも直した上でコンパイルして使ってます。

まあ、通常のユースケースではxdeltaで事足りるんだろうし、あまり大きくないファイルの差分をとるならbsdiffも便利なんでしょうが、大きいファイルの差分を継続的に生成したい、という狭い用途には(パッチをあてた上で)なかなかお勧めです。

あけましておめでとうございます

今年の目標を立てるにあたって、去年の目標を確認してみたら、365日ブログを書くとか宣ってますな……。実際のところは一月の冒頭で更新が途切れて年間で17エントリ、色々と酷すぎる。

自分の場合、書くことは好きなので去年も体調崩れてた時期以外はtwitterやfacebook、なくなってしまったけどwassrなんかで年中なにかしら書き散らしていたものの、まあブログに書くほどまとまったことを書きたくなるようなことはそうあるわけでもないし、今年は無茶な目標を立てず、週に1度更新すれば楽に達成できる年間50エントリあたりを目標にぼちぼち始めてみようかと思います。

OSS関係だと、去年から公開しているSmart::Optionsの完成度を上げていきたいのと、それとは別に何かしら新しいものを出したいなと思っています。プリキュアも無事今年は続くようなのでAcme::PrettyCureをupdateすることが出来そうです。今年は毎週リリースとかしないで済むようなつくりにしたいな!

Androidアプリもそういえば全然更新してないなあ、と。LDRoidは今も自分で使い続けてますが、いい加減4.0以降の新しいUXとかけ離れ過ぎてるので、一度1から作り直そうと思っているところ。あと色々話題になってるSmartNewsは良く出来てるなあと思ったので、あんな感じのUIでRSSとかtumblrとか横断的に見られるようなの作りたいですね(Flipboardとどう差別化するかってのはありつつ)。そして、今年はいい加減iOSアプリも作ってみようということで、大晦日にiOSデベロッパープログラムに登録したけど、まだメール届かないよ! どうなってんのApple!

と、色々書き連ねてきたけど、去年実感したのは何より健康あっての人生。食事と運動に気を使いつつ、一年を通じてフルパワーで稼動できるようにしていくのが、目標というよりは誓いだなあ

2012年をまとめてみる

毎年この時期になると「もう1年経ったのかよ!? 何もしてねえよ!」という気分と「ようやく1年か……今年も一年盛り沢山すぎだろ」という気分がごた混ぜになって押し寄せるんだけど、今年は個人的に本当に色々激動すぎたので、例年よりもうちょっと真面目にまとめておこうと思った。

今年の頭はクックパッドのAndroidアプリを作っていたり、群馬のペンションまで有志でハッカソンに参加したりとか色々と有意義に過ごしてたんだけど、去年の後半くらいからじわじわ悪化してた体調が春くらいに本格的に怪しくなってきて、5月の連休のタイミングでクックパッドを退職することに。結局、クックパッドには1年弱くらいしか居られなかったんだけど、AndroidアプリがネイティブからWebViewハイブリッドに切り替わる過渡期に立会えたりとか色々な経験をさせてもらえた。

退職後も嘱託的な形でクックパッドの仕事もしていくことになってたんだけど、更に具合が悪くなって6、7月は家で寝てるだけのことが多い感じに。この時期に1日入院して検査をした結果、体調不良の原因は非アルコール性肝炎でほぼ間違いなさそうということに。現時点では有効な治療薬は無いようで、最も効果的な治療は「痩せること」。幸い、飯を作るのも食べに出るのもしんどいような有様だったので、とにかく寝てたら体重ががんがん減り(一時135kgくらいになったので20kg強痩せた)、8月くらいでようやく「仕事しないとやばいな」と思えるくらいに回復してきた(いい加減蓄えが無くなったのもあったけどw)。

実のところ復職については全くのノープランだったんだけど、facebookで近況を報告したところ、ありがたいことに何人かの方に声をかけて頂くことが出来て、あちこち話を聞きに行ったり、そのまま面接したりというのを真夏の暑い時期にやっていた。今まで2回転職をしていたんだけど、どちらもなんとなく(そろそろ別のことをしようかな)と思っていた時に声をかけてもらうという受け身の転職で、新卒の時も色々あって自分で選ぶということをしなかったので、今回の転職はありがたいながら社会人人生で初めて自分で選択をするターンがまわってきた感じで、結論が出るまでに無い頭を絞った経験はきっと将来も役に立ちそうだなあと思った。

そこからの3ヶ月はなんというかもうあっという間で、特に入社した9月や翌10月なんかはtwitterのログなんかを見てもツイート件数多過ぎて浮き足立ってる感じだったけど、最近ようやく色々な意味で落ち着いて仕事が出来るようになってきたかなという感想。

今年に限ったことではないんだけど、今年は本当に沢山の人に迷惑をかけ、心配をさせてしまい、そして助けてもらった。来年こそは地に足つけて自分の問題はひとつずつ片付けつつ、今年受けた恩を色々なところへ返していけるようにしたいです。

KDPで本を売ってみた

kindleの国内展開とあわせてスタートしたKDP(Kindleダイレクトパブリッシング)。早速、Plack HandbookPerl テスティング ハンドブックなんかが公開されている。自分も一度何か売ってみたいなあ(単著もないのにとか言われずに済むし!)と思っていたものの、そんな都合良く本にしやすい量の文章を持ってないしなあ……と思っていたものの、去年一年間かけて食べてきたラーメンをまとめたブログがあったことを思い出して、あれならそれなりに量(129エントリありました)もあるし、全部ではないものの殆どのエントリに写真はついてるし、皆ラーメン大好きだし、丁度いいんじゃないかということで本にしてみることに。

まずはepub形式のファイルを作るということで、方法を検討。tumblrからepubへ直接変換するサービスなんかもあるようだったんだけど、件数の制限があったりするので tumblr → バックアップツールでローカルHTMLへ → Sigilでepubに という手順をとった。SigilはWin版もMac版もあるepub編集ツールで、HTMLをインポートすると中で参照してる画像もepubリソースのほうに入れてくれたり、インポートしたHTML中のh*要素を見て目次(toc)を自動生成してくれたりとか色々と気が効いてる。で、一応読めるepubになった(murasakiというepubビューワで確認)ので、KDPの管理画面から書籍情報を登録しつつ、ファイルをアップロード。しばらく待つと変換が済むので、価格とかを決めて保存すると、あとはレビューが済めばもうAmazonで買えるようになる。

なんというお手軽な……。レビューは最大2、3営業日かかると書いてあったけど、自分の場合は一晩で済んでいた模様。

さて、買えるようになったので自分もAndroidのkindleアプリで買って読んでみたんだけど、どうにも色々とイマイチ

  • そのままだと唐突に本文から始まる
  • 冒頭の章がちゃんと改ページされてない(←これは自分の作成ミス)
  • 目次が呼べない

表紙に関しては、epubでは特定の画像に「これは表紙の画像だ」というメタデータを設定できるらしく、Sigilにも勿論そのための設定があった。Kindleはepubの表紙とは別に表紙を設定できる(Amazonでの書影に使われる)けど、epubの表紙を設定しとかないとkindle端末で1ページ目に出てこない模様。

目次についてはtwitterでボヤいてたら@lost_and_foundさんが丁寧に教えてくれたんだけど、要するにメタデータ(XML)のTOCだけでなく、HTML形式のTOC(目次)も生成しないとKindleで目次として扱ってくれない、ということらしい。そしてSigilにはHTML形式目次を出力する機能もちゃんとあるのでした……。

その辺を修正して再アップロード。最初の時に気付いてなかったけど、アップロードするとプレビュー用のファイルをダウンロード出来るようになってて、PC向けのKindleアプリや、専用のKindleプレビューツールで確認できる。再アップロード分はまだレビュー中だけど、そのうちレビュー通れば既にお買い上げ下さった方々の端末では自動更新される仕組みらしい。便利!

そんなわけで、気をつけといたほうが良いポイントはいくつかあるものの、epub自体の作成もKDPでのアップロードも非常にお手軽で、これだけの手間で有料で書籍販売出来る(しかもAmazonつう知名度の高いプラットフォームで)というのは色々と可能性を秘めてて面白いなあと思いました。いつかブログの焼き直しとかじゃなくてオリジナルのソースで何か本にしたい。

Acme::PrettyCure 0.08

今週はプリキュア放映お休みだけどアップデート。

今回のバージョンから試験的に $character->image メソッドで、aviewを使ってAAでプリキュアガールズの画像をターミナルに表示するようにしてみた。cursesモードで描画してるので、実行したが最後Ctrl+Cでしか抜けられないのが難点。stdoutモードだとちゃんと動かないんだよなあ……。その辺がちゃんとしたら変身時にデフォルト出力させたいですね!

https://metacpan.org/module/Acme::PrettyCure

余談

  • 初代の2人は無印とMaxHeartでちゃんと画像変わるよ!
  • でもSSの2人はフォームチェンジ後の公式画像が無いから変わらないよ……
  • 3人ほど公式画像が無い人がいるよ……
  • ハートキャッチの公式サイトはJavaScriptで画像切り替えしてて無駄に頑張ってる感

isucon2に参加してきた

isuconとは

古代中国において部族間の問題を解決するために互いに椅子を投げあって飛距離、破壊力、チューニング力などを競った伝統「椅子魂」に倣い、現代のプログラマの間で広く行なわれている個人の決闘様式である

民明書房「藤原組の歴史」より

DSC00353.JPG

というわけで、11/3に開催されたisucon2にteam 50ms or dieの一員として参加してきました。

myfinderさん、bonnuさんがプロファイリング等でどんどん不味そうなところを見つけていくので、自分はアプリ(lib/Isucon2.pm)を読みつつ、決まった方針に沿ってどんどん書き換えていこう、といった感じ。

  • 件数が少なくて固定されてるartist,variation,ticketなどをconfigに移動
  • 最新の購入履歴10件のSQLからJOINを無くす
  • buyのところで「UPDATE …. ORDER BY RAND() LIMIT 1」とかやってたので消す

あたりを午前中にやりつつもあんまりスコア伸びず。buyが遅いというのはそれなりに掴めていたんですが、そこからの対応が

  • order_requestへ入れてからstockをupdateしてる→order_requestをなくしてstockのupdateだけでシート発番と管理用CSV出力を可能に
  • 最新10件の履歴は結局memcachedでキャッシュ
  • アーティストのページの残り席数をキャッシュ→キャッシュだと毎回(購入時に)破棄されて意味ないのでCache::Memcached::Fastのdecrで数を減らしてくことにしてDB参照自体無しに(そこそこ速くなる)
  • チケットのページの空き席tableが遅いのでstockテーブルを参照せずに済むよう空き席情報をmemcachedに持つ→更新衝突が起きるのでcas使ってアトミックに

と、中途半端な対応になったのが悔やまれました。後になって模範解答を見てみると、そもそも空き席情報をmemcachedに持ったんだからbuyでtable書き込み要らないよねとか、kazeburoさんの方式だとmemcachedのincr上手く使っててcas使わなくても更新衝突しないんだなあ、とか、redisすげー、とか、workerにHTML作らせるという発想が出てこんかった……などなど反省点が多いです。

そんなわけで50msどころか全然結果が出せず見事にdieしたわけですが、色々な気付きも得られたし、久しぶりに細かいこと考えずにどんどんコード書いてみて、やっぱりこれ(コード書く)が自分のエンジニアとしてのアイデンティティなのかもなあと思ったりとか、実りの多いイベントでした。運営された方々には本当に大感謝です。isucon3も絶対に参加したいな。そして、その時は俺、絶対にアプリをフルスクラッチで書き換えるんだ……。