霊気紛争プレリリース

友人に誘われて、霊気紛争のプレリリース・トーナメントに参加した。MINT SHIBUYAのやつで、スイスドロー4回戦。 即席を狙ってアーティファクトを出す青黒という感じに組んだのだが、なぜか土地が3枚くらい出て止まってしまうことが多く、思ったように回らなかった。強い人には回ってても勝てなかったけど……。結局勝ったのは最終戦だけで、1勝3敗だった。まあ勝てたのでよしとする。

致命的な一押しがやっぱり強かった。適当なクリーチャーで相手を殴って通れば儲けもんだし、死んだらコスト4までの除去になるので損がない。あと機械化製法でアーティファクト・クリーチャーを増やして、強い霊気装置トークンみたいに使うのも気持ちがよかった。

シールドはカードプールが限られている分、戦略は考えやすいし見通しが良くて遊びやすいのだが、コンボやシナジーを考えるのも好きなので構築もやってみたい。

NANA MIZUKI LIVE ZIPANGU 2017

今年の目標 1/10

水樹奈々のライブツアーに申し込んだら当選したので、名古屋公演を観に行ってきた。水樹奈々は好きだけど特別に聴き込んでるわけでもなく、なのはとシンフォギア以外は有名なのをちょっと知ってるくらい。水樹奈々なら曲を知らなくても楽しめるだろうとは思っていたけど、流石に予習しないのもなぁと思って、当日の朝にNEOGENE CREATIONを買って新幹線の中で聞いていた。

ライブはアーティスト単体のライブとしては過去最高に面白かったと言ってもよいと思う。幕間のつなぎのバンドメンバーの紹介、バックダンサーの紹介、ショートドラマ上映とすべて高いクオリティで、まったく飽きることがなかった。そして当然、水樹奈々本人の歌唱力と存在感は凄まじく、大半の曲を知らない or 今日初めて聞いたという状態であっても、予想通り純粋に音楽イベントとして楽しむことができた。あの歌声を大ホールの整った音響設備で聞くという体験そのものに価値がある。

30曲近く歌ったはずだが、以前から知ってた曲はETNERNAL BLAZEとUNLIMITED BEAT、そしてギターソロ+ボーカルという変則構成のPrayだけだった。Prayはバンドメンバーの1人のソロ+歌唱を毎公演違う組み合わせで行う予定らしく、たまたま知ってる曲に当たったのはかなり運が良かったっぽい。

この記事を書きながらもう一度NEOGENE CREATIONを聞いているが、やっぱりライブで聞いてから曲を聞き直すと、感じるものがありすっと頭に入ってくる。普段はアニメ等で聞いた思い入れの深い曲がライブで披露されてアガるという順番なので、逆でも同じような効果が得られるんだなぁという気づきがある。この思い入れが深まった状態で、もう一回ライブの歌声を聞きたい。

まったく関係ないが、バンドがドラムセットを3つ含むという変則的な構成だったのがちょっと気になった。そのうちの1人は太鼓など違うパーカッションを担当していることもあったが、他の2人はずっとドラムセットを叩いていた。どういう効果があるんだろう(違う譜面を叩いてたりするんだろうか)。

2017年の目標

量的な目標

ライブに10回行く

去年は2月末のシンフォギアライブで初めてライブを経験してから、結構な回数ライブに参加した。

ちょうど10回ですね(Updated 2016/01/18) EGOISTのライブも行ったので11回だった。楽しいので今年も同じくらいはライブに行きたい。

映画を10本見る

映画も積極的に見たいんだけど、拘束時間が長いとなんとなく気後れしてしまう。しかし映画に行かなかった時間で漫画を読んでいることはよくあり、結果的には映画見れるじゃんと思ったことが何度もあった。

小説を10冊読む

最近はめっきり小説を読まなくなってしまった。去年読んだのって伊藤計劃くらいなのでは……。さすがにどうかと思うので読む数を増やしたい。自分で小説的な物を書くと、文体があまりにも味気なくてつらい気持ちになるので引き出しを増やしたいというのもある……。

旅行に10回行く

国内8回、海外2回くらい?何を旅行と呼ぶかは難しいが、1泊以上して、かつ特定のイベントへの参加よりも多くの事をしたら良いということにする。


Webサービスを3個作る

不特定多数のユーザが利用することを想定したものに限る。

ゲームを1本作る

あんまり公開とか考えず、自分が楽しければよいくらいの気持ち。最近のゲーム技術を勉強しておきたい。

上2つは過程でいくつか内部ツールを作ることになるんじゃないかと思う。その個数もカウントすると面白そう。

GitHubに200 Contributionsする

200という数値に絶対的な意味はなくて、去年は160 Contributionsだったようなので、もうちょっとアクティブにコードを書きたいくらいの気持ち。

質的な目標

ICFPCで1位を取る

去年は2位だった。打倒Unagi。

Magic: the Gatheringをプレイする

去年の終わり頃に遊んで楽しかったので、情報を追いかけてみる。

はてなブログのデザインを直す

PCで読むと文字がでかくて気持ち悪いので、納得の行くCSSを書く。

ブログで目標のトラッキングをする

なんかブログというとある程度まともな文章を書かないといけない気持ちになってしまうが、本来自分のブログに何を書いたってとやかく言われる筋合いはない。Twitterレベルの雑な更新でもちゃんとブログに書いとくと検索しやすくて良い気がする。

聖地巡礼

この記事はドイツのトリアドベントカレンダー1日目の記事です。

公式サイト(繋がんないけど仕様なんですかね)に書いてある座標の様子です。

周囲を見渡すとこういう風景で、ちょっと座標ずれてるのでは?

西に行くとそれっぽい場所があった。

オッ

ダメ

という訳で白鳥はいたもののドイツのトリは撮れませんでした。自然公園としては気持ちがよさそうなので、やることなかったら遊びに行くのもいいのでは。芝生部分はそこら中にペレットが落ちています。 あと近くにあるBMW博物館は車に興味がなくても面白かったです。オススメ。

おまけ

イタリアのトリです。ローマのなんだっけ、フォロ・ロマーノとか言う所で見ました。

イタリアのあずにゃんです。イタリアのオタクショップに行ったらハンガリー人のオタクに日本語で話しかけられてやばかった。

明日はあっきぃさんです。

さんまの梅煮

食べたくなったのでさんまの梅煮を作りました。

あずにゃん、さんまの梅煮、炊き込みご飯、大根と豚バラの味噌炒めです。

さんまの梅煮:こんぶつゆ25cc、日本酒25cc、梅干し(塩分22%)2個、水適量(煮込むと蒸発するので量はどうでもよい)を煮立ててから弱火にして、頭と内臓を取ったさんまの筒切りを投入して煮込みます。落し蓋がないと味がうまく行き渡らないと思います。 今回は1時間半くらい煮込んだところ、骨まで柔らかくなりました。微妙に生ぐさいので生姜を入れたほうがいいかも知れません。前回はネギを入れたんですが、塩味をめっちゃ吸ってしまいネギとして食べるのは厳しい感じになりました。というかそもそもこのレシピだと塩が強いので、こんぶつゆの代わりに塩分のないダシを使うのが良いかもしれません。今度やります。

炊き込みご飯:米2合にこんぶつゆ25cc、日本酒25cc、戻したひじき(乾燥時5gくらい)、きざみ揚げ、まいたけを入れて炊きます。結論から言うと味が薄いので、醤油を倍量くらい入れてよいと思います。まいたけは食べるとあまり味がしなくなっているのでご飯にダシが出ているんだと思いますが、よく分からないです。でも動物性の具を使わずにそれなりの味になりそうな気配は見せているので、ベジタリアンの人になんか振る舞うとき便利かもしれません。

大根と豚バラの味噌炒め:大根(いちょう切りで24枚くらい)、ネギ1本、豚バラ100gくらいをこの順で炒め、味噌小さじ2くらいとチューブ生姜適量を日本酒と水で溶いて和えます。豚バラをフライパンの上で放置しておくと自分の脂で勝手に揚げ焼きになり、香ばしくなるということを発見しました。大根は火の通りが遅く、固いと悲しい気持ちになるので忍耐が必要です。

あずにゃんfigmaです。Amazonの履歴によれば6年前に買ったらしいです。当時はけいおんのアニメ2期が放映されていましたが、今もNHKBSで放映されていることが知られています。

あずにゃんとEscapeキー

新しいMacBookでは、キーボードからEscapeキーがなくなるらしい。

最初にそう聞いたとき、僕はただ、ふぅんと思っただけだった。Escapeキーなんてそんなに使うものでもないし、消えても困るものではないだろう。

「あ、また何か変なこと考えてましたね」

しかし、現実は時として予想外の景色を見せるものだ。今、僕の手元にある新しいMacBookは、女の子がEscapeキーの働きをしている。


「私がそのMacBookのEscapeキーです。よろしくお願いします!」

僕がMacBookを買ったとき、彼女は突然そのように挨拶してきた。腰まで届くかというような黒い髪を頭の両横で結んで垂らしている、小柄な女の子だ。なんだこいつ、と思う間もなく彼女が説明を始めたところによると、Escapeキーがキーボードからなくなる代わりに、付属の女の子がEscapeキーとして働くのだという。そんなことあり得ないだろうと思って彼女を試したのだが、僕が彼女に合図を送ると、MacBookの画面は本当にEscapeキーが押されたかのような振る舞いを見せる。

「分かっていただけましたか?」
「ああ、分かったよ。Escapeキーを押したい時には君に言えばいいんだね?」
「はい、そうです!」

元気よく応える彼女。

「でも、名前がないとちょっと声をかけにくいな。君はなんて言うの?」
「うーん、Escapeキーなのでこれと言って特別な名前はないんですが……。製造コードは『ナカノアズサ』となってます」
「じゃあ『あずにゃん』でいいかな。アズサの『アズ』を、あだ名っぽく可愛くした感じで」
あずにゃん……あずにゃん。いい響きですね。じゃあ改めまして、よろしくお願いします!」

こうして、僕と「あずにゃん」の生活が始まった。


女の子がEscapeキーであると言っても、そもそもEscapeキーはそんなに使うものでもないので、必然的に彼女の仕事は少なくなる。一番よくある出番はゲームを終了するときで、僕はタイトルから終了の項目を選んで終了するのでもいいと思っているのだが、ゲームで一通り遊んでいざ終わろうとすると、それまで横で画面を眺めながら、へぇ、とか、おぉ、とか声を上げていたあずにゃんが、期待に満ちた目で僕を見つめてくる。Escapeじゃなくても終了できるんだけどな、と思いつつも仕方ないかという気持ちでEscapeキーの入力をお願いすると、あずにゃんは待ってましたとばかりにEscapeのキーコードを発行して、ゲームを終了するのである。一瞬だけ画面が暗転してデスクトップに戻った後、あずにゃんはこちらを向いて、どうだ、やってやったぞとばかりに自慢気な笑顔を見せてくるので、まあ、こんな可愛い顔が見られるのであれば次もお願いしようかな、などと僕は考えてしまうのだった。

ゲーム以外でEscapeキーが必要になる場面は、日本語入力の変換を間違えた時が一番多い。変換の文節区切りがうまく認識されなかったり、開こうと思った漢字まで変換されてしまった時などはEscapeキーの出番となるのだが、しばらく一緒に過ごしているとあずにゃんの方も僕のそういった癖を飲み込んでくるようで、あ、またですねと言いたげな顔で促してくる。心の中を見透かされているような気恥ずかしさを覚えつつ、うん、間違えてしまったからEscapeキーお願い、と頼むと、してやったりという表情を隠そうともせず、誇らしげに変換をひらがなまで巻き戻してくれる。そんなあずにゃんを見ていると、なんだか心強い味方ができたような気がして、僕の心が温まるような感覚を覚える。


ある日、あずにゃんとEscapeキーを巡ってケンカをした。発端は僕がVimを使い始めたことで、最初の不慣れなころは何か操作をするたびにEscapeを押してNormalモードまで戻る羽目になり、いちいちあずにゃんに頼んでいた。突然仕事が増えたあずにゃんは嬉しそうで、僕が「あっ」という声を上げるたびに、Escapeを発行したくてたまらないらしく、猫じゃらしを前にした猫のように、うずうずした様子を見せていた。

しかし、僕がVimの操作に習熟していくにつれて、Escapeを使う頻度は減ってきて、代わりに<C-[>を使うことが多くなってきた。別に大きな理由はないのだが、やはりホームポジションから手を動かさずに入力できるし、自分のペースで打てるため、こちらの方が使いやすい。次第に、あずにゃんにEscapeキーを頼む機会も減っていき、あずにゃんはなんだか寂しそうな表情を見せるようになった。

「<C-[>はいいですね、いつも使ってもらえて。私もEscapeキーなんかじゃなくて、Ctrlになればよかったのかな……」

あずにゃんが時折こう呟くのを聞くと少し胸が痛んだが、<C-[>のほうがなんとなくしっくり手に馴染んでしまったこともあり、段々とEscapeキーからは疎遠になっていった。

そしてある日。僕が久しぶりにゲームをしようとすると、なぜか起動しなくなっていた。そんなはずはない、と思って何回か繰り返すと、どうやら起動しないのではなく、起動した瞬間に終了させれられているようだということに気がついた。もしかして、と思ってあずにゃんを見ると、顔をクッションに半分うずめて、怒っているような、泣いているような、どっちつかずの表情を少し見せた後、そっぽを向いてしまった。

あずにゃん、怒ってる?」
「別に、怒ってないです」
「でも、ゲーム……」
「さあ、知らないです。どうせVimの操作を間違えて、設定ファイルを壊したんじゃないんですか」

取り付く島もない。僕はゲームを諦めて、Twitterを眺めることにした。独創的なVimプラグインを書くことで有名な人が、今日もVimネタのツイートを繰り出している。

Vimはいいですよね、こんなに好きでいてくれる人がいて。私の出番なんてないんです」
「そんなこと……」
「私だって、最初の頃は仕事が増えて、大変だけど楽しかったです。Escapeキーなんて全然使われないと思っていたのに、突然主役みたいになって。ああ、Vimっていいな、Vimがあれば、Escapeキーでもこんなに使ってもらえて、話しかけてもらえるんだって、そう思いました」
「でも……」
「でも、モードを切り替えるのは<C-[>の方がやりやすいんですよね。Vimも最初からそのキーバインドがあるし、元からそういう物だったんですよ。勝手に調子に乗って、喜んでた私がバカみたいじゃないですか。結局Vimに踊らされてるだけで、そのVimにもこんなに熱心なファンの人がいる」
あずにゃん……」
「もう、ほっといてください。Escapeキーなんていらないんでしょう!」

僕は、それ以上何を言えばいいのか分からなかった。MacBookを閉じた後も、頭の中ではあずにゃんの言葉がぐるぐると渦を巻いていた。

ISUCON6予選で負けたので反省します

ICFPCが楽しかったのでまたチーム戦しようという話になり、かねてから興味のあったISUCON6にチーム「イーグルジャンプ」として、id:pepsin_amylaseとmkutとともに参加しました。Python実装を選び、8時間かけて12830点しか取れず、社会的には完全に人権を喪失しました。以下、反省文です。

やったこと

  • Opsフローの策定 (osa_k)
    • 基本的にはpull-reqベースで開発を進める。masterは常にデプロイ可能な状態に保っておき、featureをマージするときにはmasterからfast-forwardできることを要求する。
    • 設定ファイル類はすべてリポジトリに入れておき、通常のデプロイ操作だけでnginxやMySQLの設定まで変更できるようにする。
    • デプロイ時に変な操作をして環境破壊することを防ぐため、Rundeckジョブを叩いてデプロイする。
  • 本番サーバの他にテスト用サーバを立てる (osa_k)
  • 秘伝のタレnginx.confとmy.cnfをサーバに置くが、たまたまアプリ実装のバグでアプリの起動に失敗し、原因を切り分けるため設定ファイルをロールバックしたまま忘れる (osa_k)
  • RundeckとSlackのインテグレーションを設定する (osa_k)
  • 静的ファイルをnginxで配信する (osa_k)
  • isutarをisudaに併合する (mkut)
  • ついでにスター処理をRedis化する (pepsin_amylase)
  • ログイン処理とキーワード一覧の取得をRedis化する (pepsin_amylase)
  • リンクのsha1をキャッシュする (pepsin_amylase)
  • htmlifyの結果をキャッシュする(別プロセスでひたすら最新30件のキャッシュを作りRedisに突っ込む) (osa_k)

やってよかったこと

情報共有の時間を取る

全員の作業のキリがよくなりそうなタイミングで小休止を挟み、現在自分が何をやっているか、何が分かったかという情報を共有する時間を設けることで、全員が全体の状況を把握できるようになるとともに、改善案を取捨選択して重要そうなものに注力することが可能になりました。相談せずにずっとコードを書いているとだんだんノッてきて書きたいものは増えていくのですが、すべて実装する時間はないのでアイデアの切り捨てが必要になります。強制的に休憩を取ってミーティングを行うことで、全員でアイデアの共有と吟味ができるため、大きな手戻りは防ぐことができました。1人でもそのへんは同じだと思いますが、チーム戦だと誰か1人が言い出せば良いので、アイデア吟味の時間を取り忘れる可能性が下がるのが良い点です。

開発フローを定める

今回はmasterを常にデプロイ可能な状態に保ち、各自がfeatureブランチをmasterから作ってfast-forwardな状態を保つことで全体の信頼性を確保する、いわゆるGithub FlowContinuous Deliveryと呼ばれている手法を使いました。ISUCONのようにあるタイミングで必ず動くものを提出しないといけないというコンテストでは、常にmasterがデプロイ可能という状態は安心感がありました。

ただし、featureの粒度を小さく保つのが難しく、あるfeatureで関係ない箇所のバグに気づいてfixを混ぜてしまい、他のfeatureでもそのfixが必要になったため、masterからではなくfeatureからブランチを生やすというケースが発生してしまいました。こうなるとそのfixを含んだfeatureがrejectされたときに大変面倒な状況になるため、運用には専用のgitコマンド群を用意するなど、ある程度のDevOps作業が必要になると感じました。

やるべきでなかったこと

Rundeckを小規模オペレーションに使う

これが(自分が担当した中では)一番の敗因でした。コンテスト中は、アプリのデプロイ手順はテスト環境でも本番環境でも変わらないという理由により、ひとつのRundeckジョブにテスト用と本番の両方のノードを登録して、ジョブを叩く人がデプロイ先を選ぶ形にしていました。しかし、そもそもRundeckはChefやCapistranoのように、複数のサーバで同じコマンドを同時に叩くというオペレーションが主眼に置かれており、本番とテストのデプロイ操作をひとつのRundeckジョブで共有しようというのは、かなり踏み込んだ自動化をしないと無謀です。実際、テスト用サーバで作業している最中に間違ってデプロイを叩かれ、作業中のデータが消えるという事件がありました。また、ノードのマシン名やログイン情報などは手書きでXMLを編集しないといけなかったり、ジョブ定義のUIが煩雑でTry & Errorを前提とした改修に向かなかったりと、設定作業が割と煩雑なため、どうしても使いたいのであれば、プロジェクトの生成から全部スクリプトで自動化するべきでした。練習中はRundeckジョブを叩いてくれるhubotを運用していたのですが、Rundeckを通してデプロイしていると開発のテンポが悪くなることと、そもそも本番で設定がうまく行かずに動いてくれなかったため、手動でRundeckを叩く運用にしたのも良くなかったです。

とは言えGUIでサーバを触れるようにするという方針は、実行ログや処理内容が一箇所に集約できて管理が楽になるという点で、間違っていなかったと思います。後述のように本番環境と開発環境の分離がうまくできず、Rundeckで管理する対象の大きさが不必要に膨れ上がってしまった点が問題なので、これは本当に集約管理しないといけないか?という切り分けをリソースごとにじっくり考えるべきだったと言えます。

環境設定をしていた時間のほとんどはRundeckの設定を調整していた時間になっていたので、この規模の用途でRundeckを使ったのは完全にオーバーキルであったと思います。使うにしても、設定を可能な限り自動化してやるべきでした。

開発用サーバをケチる

練習の段階では、ローカルで環境構築する手間を省くために個人ごとに作業用VMを立てようという話をしていたのですが、AzureのFree tierプランでは1リージョンに4コアまでしかマシンリソースを置けないという制約があり、面倒だったので開発用兼テスト用サーバの1台しか用意しませんでした。また、前述のようにRundeckの設定が煩雑だったため、ノード数を増やすと作業量が増えてしまうという問題もありました。結果として、3人チームなのに2人しかサーバ環境が使えず、1人はローカルで環境構築する必要があるという二度手間になってしまいました。

急な方針転換はオペレーションが混乱するため、可能な限り避けるべきです。設定ファイルのチューニング忘れも完全にこの辺の混乱が尾を引いてしまった形です。また、アプリの開発環境整備は、処理系のバージョンを揃えたり、DBの導入をする必要があったりと結構面倒な作業を(特にMacを使っていたりすると)含むため、なるべくなら自動化されたものをそのまま使う方が良いです。

開発環境とテスト・本番環境の分離をはっきりしない

開発用サーバとして用意したサーバは、実質テスト用サーバを兼ねており、作ったブランチを試したいときにはアプリをデプロイし、ベンチマークに投げるという運用がなされていました。しかし、当初はデプロイ処理の大部分がRundeckジョブとして記述されており、ちょっとしたテストをするにもブランチをpushしてどこかにデプロイするという作業が必要で、全体で1〜2分ほどかかっていたため、かなりまどろっこしい運用になってしまっていました。

後半ではデプロイ作業の大部分をdeploy.shとしてまとめ、Rundeckジョブではこのシェルスクリプトを叩くだけになりました。こうすることで、開発用サーバ上でも開発者がdeploy.shを叩くだけでデプロイできるようになったのですが、開発環境はコードの編集からデプロイまでの素早いイテレーションが求められ、テスト環境では可能な限り本番に近づけた運用が求められるということに気づかず、ごちゃ混ぜの運用をしていたのは大きなミスでした。そもそも今回は短時間コンテストな上、間違えて環境を破壊しても復帰が容易だったので、テスト環境という概念自体が不要だったと思います。

プロファイルを取らない

ボトルネックの特定は主にnginxのアクセスログの解析と目視のコード確認で行っており、トップページのレンダリングにかなり時間がかかっていることは比較的早い段階で分かっていたものの、キーワードやログイン情報のキャッシュなど、本質的でない箇所の高速化に時間を割いてしまい、htmlifyのキャッシュに取り掛かったのは終了2時間前でした。ちゃんとした経験か洞察力があれば、巨大な正規表現ボトルネックであると看過できたはずなのですが、そうでない以上は闇雲に最適化を進めるのではなく、行レベルのプロファイリングなどで実行時間を測定し、定量的にボトルネックを探すべきでした。

このあたりはサーバ設定が遅れたことでオペレーションが混乱し、データが欲しいときにすぐ得られる状況でなかったため、nginxのログの確認すらスムーズに進められなかったことも大きな原因になっていると思います。環境構築の遅れはとにかく致命的です。

まとめ

せっかくのチーム戦だし、普段から興味のあったオペレーション役をやりたいと思っていたのですが、過度に複雑なオペレーションを組んでしまって爆死しました。開発経験なさすぎですね……。ツールの使い方や最適な開発フローなど、自分1人の開発でも勉強できた点は多かったと思うので、個人プロジェクトでいろいろ試して来年のISUCONまでに経験値を積みます。