ISUCON7本戦は惨敗でとても悲しい気持ちになりました

ISUCON7本戦に出てきました。 結果はスコア0、最終的にはFAILで終わるという惨敗でした。

出場メンバーは会社の同僚との3人組で、予選と同様に他の2人がアプリケーション担当、僕がインフラ担当という役割分担をしました。

残念な結果となってしまい、とても悲しい気持ちなのですが、その思いを昇華させるためにも当日やったこと、考えていたことなどを記録しておこうと思います。 尚、悲しい結果に終わったこともあり、後悔や言い訳の多い見苦しい文章となっています。あらかじめご了承ください。

当日の流れ

10:00 にレギュレーションが閲覧できる様になりました。 しばらくは運営側でid, passwordの配布に時間がかかっており、コンテストが始まらなかったので、その間に3人でレギュレーションの読み合わせを行いました。単純に読んでいるだけでも、複雑なアプリケーションで単純な最適化は難しそうだなーという印象を受けました。

最初の30分は僕が各サーバーのセットアップ(git管理下に置く、各人がsshできる様にauthorized_keysを配置する、netdataの監視を仕込むなど)を行い、他2人がDBのデータの確認とアプリケーションのコードを読んでの概要把握を行いました。

その後、最適化の方法をざっくり話し合い、以下の方針を決めました。

  • 方針1. calc_status が明らかにヘビーだから、なんらかの形でキャッシュする必要はありそう
  • 方針2. dbを触ってる部分はRedisに載せていくと良さそう
  • 方針3. roomごとにスコア計算は完全に独立しているから、roomごとにhostを振り分けて、hostごとにデータを持つ様にしたらthroughputが出そう(この時点では、redisをhostごとに建ててそこにデータをstoreすることを考えていたので、redisの負荷が減りそうくらいのイメージで捉えていた)
  • 方針4. static file配信はいつもの様にnginxでgzipで配信すると良さそう

今振り返るとこの時点での方針は悪くなかったと思うのですが、結果的には「方針4」以外は実装が思う様に進まず、ほぼmergeされる事はありませんでした。

自分が後悔している事の一つは、この時アプリケーションを読んでいた同僚から「ロックが必要になる」という事を言われた際に、ロックの方法についてもうちょっと自分もアプリケーションを読み込んだ上で議論すべきだったという事です。 自分はアプリケーションのコードは1行も読んでなくて、ただ「DBでロックを獲得するコードがある」と言われて議論した結果、DBを捨ててRedisを使うならRedisのincrでロック獲得を記述できそうという結論になりました。この「Redisのincrで実装したロック」は動作はしたのですが、毎回ロック獲得トライをRedisに問い合わせて行うというコストの高い動作の為か、スコアアップには繋がりませんでした。後で同僚からは「ロックはroom_nameごとに独立してかければ良かった」と聞かされて、そこまでの知識があればこの時点でroomごとに処理するprocessを分けて、ruby内部でmutexを活用しようという提案ができたかも。。。と後悔しています。

現実には、同僚の一人が「方針1」を、もう一人が「方針2」を進め、僕は「方針4」を行った後、便利スクリプト集(deployやログ閲覧、アクセスログ回収、各ホストの状態チェックなどをローカルのマシンからコマンド一発で実行できるもの)の整備やちょっとしたパラメータチューニング(pumaが10processで動いてmemoryを結構使っていたのでprocess数を減らしてthread数を増やしたりしてた)、2人とのペアプロなどを行なっていました。

「方針4」は一応スコアに効いて、9,600ぐらいになりました。しかし、それ以降僕らのチームのスコアが上がる事はありませんでした。

同僚が2人とも苦戦していたので、僕は定期的にペアプロでハマり解消を手伝っていました。

「方針1」を進めていた同僚が「途中まで出来た」といってベンチにかけてみたところ、スコアは上がらないどころか若干下がっている様に見えたので、その時はもう少し実装を進めてスコアを上げてからmergeしようという話になりました。結局、その後そのブランチがベンチを通る事はなく、彼は最後までそのブランチで作業し続けることになりました。(余談ですが、スコアが上がらなかったのは、おそらく前述の通りRedisをロックに利用していた為では無いかと疑っています)

「方針2」を進めていた同僚もRedisでロックをかけていて、こちらもベンチがなかなか通らずずっとハマっていました。最終的にロックを色々な箇所に設定する事でベンチは通ったみたいですが、それは終了の30分前であり、スコアも上がりませんでした。

(尚、「スコアが上がらなくてもmergeだけでもしておこう」といって「方針2」の一部はmergeされたのですが、最終スコアはFAILになってしまいました。不思議に思ってコードを見返すと、分かりやすく「引数が無いメソッドコール」というバグがありました。「ベンチ通ったからmergeした」と聞いたのに悲しい。。。)

結果としては、1日を通して有効な変更をほぼ入れられず、やりたいことが実現できないまま終了してしまったコンテストとなりました。

反省

自分の反省点はいろいろありますが、大きいのは以下の2つだと考えています。

1つ目は、自分がアプリケーションを全く読み込まなかったことです。「アプリケーションの仕様」を理解してないことから、途中で2人とペアプロする際も「コード的な間違いの指摘、修正」に終始してしまい、「アプリケーションの仕様の範囲で可能な限り効率的な実装を考える」という事が出来ませんでした。特に、今回の問題は効率的な実装をするにはスレッドプログラミングの知識が求められるものになっていたと思うので、自分の知識は本当はもっと活かせたんじゃ無いかと思っています。

2つ目は、自分がアプリケーションコードをほとんど書かなかった事です。これは1つ目の反省とも繋がるのですが、アプリケーションを読み込んでない状態では改善のアイディアを考えづらく、さらに残り時間が少なくなるほど「これからアプリケーションに着手する」といった手が取りづらくなり、結果としてほとんどアプリケーションを書きませんでした。アプリケーションがボトルネックというのは初めから分かっていたので、インフラ作業を捨てるというのも1つの選択肢だったように思います。

自分は普段はアプリケーションエンジニアとして仕事をしており、ISUCONは貴重な「インフラ知識をつけることができる、インフラオペレーションに慣れる事ができる」機会となっています。カーネルミドルウェアのチューニングをしてマシンを効率的に利用したり、デプロイツールなどを自作して様々なタスクを自動化するのは僕にとって楽しくて、ISUCONではインフラ担当としての参加にこだわっていました。ただ、今回はそのこだわりが良く無い方向に働いたな、と感じています。

結論

今年は悔しい結果となったので、また来年頑張りたいです!!!

謝辞

運営の皆さん、お疲れ様でした。綺麗に整理されたコードで複雑なアプリケーションが実装されており、運営の皆さんの気合を感じました。取り組みがいのある、良い問題だったと思います。ありがとうございました。

ISUCON7予選をギリギリの18位で突破しました

会社の同僚と一緒にISUCON7予選に出場しました。 結果は18位、ギリギリでしたが何とか予選突破できました。事前にチームで練習したり、便利スクリプト集を仕込んだりしていたので、練習の成果がちゃんと発揮できてよかったです。

同僚が当日やったことについてブログを書いてくれました。余裕があれば、僕の観点からのISUCON7予選についてもブログ書きたいと思ってます。

RubyKaigi 2017 に行って来ました(3日目)

発表

10:00-10:40: Compacting GC in Ruby by @tenderlove

10:50-11:30: Ruby for Distributed Storage System by @tagomoris

https://www.youtube.com/watch?v=KrWhhgWHTwE&feature=youtu.be

13:00-13:40: Bundler 2 by @colby-swandale

13:50-14:30: JRuby at 15 Years: Meeting the Challenges by @headius & @enebo

14:40-15:20: Boosting Performance Bottlenecls: Improving Boost Type by 60% by @jules2689

https://jnadeau.ca/presentations/rubykaigi2017/

15:50-16:30: Improving TruffleRuby’s Startup Time with the SubstrateVM by @nirvdrum

16:40-17:40: Towards Ruby 3x3 performance by @vnmakarov

発表感想

あとで追記予定です。Performanceの話が色々聞けて良かったです。特に、TruffleRubyと最後のKeynoteでのMJitの話が、夢のある話で印象的でした。

全体振り返り

7本x3日 = 21本の発表と、LT12本を見ていて、振り返ると盛り沢山でした。 どれも面白かったですし、言語処理系やパフォーマンスに興味を持ってる自分としては、詳しい人の話を聞けて楽しかったです。JRubyやTruffleRubyもかなり注目しているので、中の人を見れたのが個人的にグッドでした。

懇親会では、以前から話してみたかったRubyコミッターの方たちと話せて、良い機会になりました。自分の中でのOSSへのモチベーションも上がった気がします。 総じて、行って良かったなーと思います。

RubyKaigi 2017 に行って来ました(2日目)

発表

9:40-10:40: Keynote by @matz

10:50-11:30: An introduction and future of Ruby coverage library10 by @mame

13:00-13:40: Improve extension API: C++ as better language for extension by @kou

slide.rabbit-shocker.org

13:50-14:30: Automated Type Contracts Generation for Ruby by @valich

14:40-15:20: Asynchronous and Non-Blocking IO with JRuby by @jkutner

15:50-16:30: Bending The Curve: Putting Rust in Ruby with Helix by @chancancode and @hone

16:40-17:20: Write once, run on every boards: portable mruby by @yurie

17:30-18:30: Lightning Talks

発表感想

Keynote by @matz

RubyのModuleをベースにして、色々なプログラミング言語の機能を取り入れながら、Moduleが色々な役割を担うようになってきたよって話でした。 最近増えたRefinementやprependの狙いや位置付けについて、matz本人から話を聞けたのは良かったです。こうしてまとめられてるのを見ると、確かにModuleは色々な役割を担っててなんだかんだで複雑になってる気もしました。個人的には、namespaceとしての利用が面白いと思ってます(rubyのrequireはただRubyコードを実行するだけでimport, exportみたいな概念はないので、Moduleとしてglobalな空間での衝突を避けないと大変なことになる。。。w)

An introduction and future of Ruby coverage library10

test の coverage とはなんぞやぞいうお話と、Ruby の coverage library をもうちょっと良いものにしようとしてるよというお話。 Ruby で test coverage を計測したことなくて気付いてませんでしたが、line coverageしか公式ではサポートしてない状態だったらしいです。機能追加してくれるのはありがたいと思います。

Improve extension API: C++ as better language for extension by @kou

C++Ruby の extension library を作るなら、こんな風に C++ の中で Ruby っぽく書けて良いよ、みたいな話でした。 APIを考えるのが好きみたいで、実際にlibraryとしてある程度動くものを作ってるのがすごいと思いました。発表中に「binding libraryを作りたいわけじゃない」と言ってましたが、むしろbinding libraryを作る際に役立ちそうだと思いました(Rubyのオブジェクトを触ったりRubyのメソッド定義がやりやすくなってるように見えたので)。

cf. https://github.com/jasonroelofs/rice

Automated Type Contracts Generation for Ruby by @valich

RubyMineの中の人による、Rubyのテストコードから型情報を集めてうまく集約して出力する仕組みを作っている(作った)というお話。 型情報を集約するロジックの話はなかなか面白かったですし、RubyMineが色々機能拡張してるのはすごいと思いますが、全てのケースをテストで網羅するのはちょっと難しそうだなーと感じました(発表してる人は、みんなの力を合わせれば可能だ、と言っていてちょっと夢を感じましたが)

Asynchronous and Non-Blocking IO with JRuby by @jkutner

JRuby で非同期ノンブロッキングIOを利用したいケースのサンプル実装として、RatpackとNettyを利用したHTTPサーバーアプリケーションを作ってみたよってお話でした。

cf. https://github.com/jkutner/jruby-ratpack-async-demo

JVM系だとPlay FrameworkもノンブロッキングIOとして有名な気がするので、JRubyから利用は出来ないのかが個人的にはちょっと気になりました。

Bending The Curve: Putting Rust in Ruby with Helix by @chancancode and @hone

Rust で Ruby の native extension を作る為のライブラリとしてHelixというものを作っていて、こんな感じだよというお話。 2年前のRubyKaigiでも話してるのを聞いていたので、ちょっと気になっていました。Rustのマクロを使い倒してるみたいで、強力なマクロシステムを持つ言語は良いなと感じました(Cのマクロはただの文字列置換ですが、Rustのマクロはparseした結果に触れるみたいです。コードを見てると、identtyの様にidentifierとtypeが明確に区別されていたので、変なミスや予想外の変換が防げて良さそうだと感じました)

Write once, run on every boards: portable mruby by @yurie

Rubyマイコン上で動くプログラムを書いてるよ、一度書いたプログラムを共通で使えるようにしていこうよってお話でした。 デモでトラブル続出していたので大変そうでした。

Lightning Talks

たくさん発表があって説明しきれないですが、みんな発表のレベルが高いしユーモアセンスもあって面白かったです。LTは自分も挑戦してみたいなーと思いました。

懇親会

mirakuiさん、matzさんみたいな前から話してみたかった方と話せてよかったです。 matzさんには写真まで撮ってもらえて、嬉しかったです。

matzさん

Rubyのeachやブロックはかなり先進的だと以前から思っていたので、どういう経緯で「eachメソッドという発想に至ったのか」みたいな話を聞きました。each的な存在はsmalltalkから着想を得たと言っていて興味深かったです(調べてみたら、smalltalkにはcollection closure methodと呼ばれるメソッド群が存在していて、その中にrubyのeachに相当するdoの他、select, sort などblockを受け取ってcollectionに作用するメソッドが存在することがわかりました。smalltalkすごい)。forwhileみたいなキーワードになってた方がメソッドよりもかなり簡単に最適化出来るはずで、どういう発想でそこに至ったのか気になってたので聞けてよかったです。ついでに、他のプログラミング言語にもiteratorを宣言する構文があった(関数の引数としてiteratorを渡せるようになっていた)という話を聞きましたが、言語の名前は忘れましたw

mirakuiさん

Cookpad CTO 大変ですか、みたいな話をしました(チーム編成、評価制度など)。 海外と国外の開発どう進めてますか、という話も興味があったし自社でも色々考えてる部分なので聞いてみました(海外と国内で大きくシステムを2分してる。海外はその中でさらに国ごとに機能を分けてる、それは料理は地域固有の文化に密接に結びついており、文化ごとに適切な表現や探し方、機能が異なってくるから、そうせざるを得ないと思ってる、など)。やはり、どのサービスも海外展開というと苦労してるんだなー、という印象を持ちました。

2日目総括

発表をたくさん聞けて大満足でした。特に、LTで「もっと長い時間で話せる内容の発表」がたくさんあり、全体のボリュームが割増されていた様に感じます。

RubyKaigi 2017 に行って来ました(1日目)

発表

10:30-11:30: Keynote by @n0kada

https://slide.rabbit-shocker.org/authors/nobu/rubykaigi-2017/

13:00-13:40: Fiber in the 10th year by @ko1

13:50-14:30: How Close is Ruby 3x3 For Production Web Apps? by @noahgibbs

http://bit.ly/kaigi2017-gibbs

14:40-15:20: Gemification for Ruby 2.5/3.0 by @hsbt

https://www.youtube.com/watch?v=VKm93Mwe__k&feature=youtu.be

15:50-16:30: How to optimize Ruby internal by @watson1978

16:40-17:20: mruby gateway for huge amount of realtime data processing by @naritta

17:30-18:30: Ruby Commiters vs the World

発表感想

Keynote by @n0kada

Rubyコミッターの日常はこんな感じですよ、というお話。 ライブコミットやスライドのライブ編集など、その場にいる事で楽しめるコンテンツが盛り込まれていて、会場で聞くことができてよかったです。Rubyのコードはコアっぽいところはそこそこ読んでるつもりですが、parse.yは複雑すぎて変更が難しくなってると感じます。。。

Fiber in the 10th year by @ko1

Fiberを10年前に作ったけど、意外なところで使われて嬉しかったし、ちょっと微妙な実装だったところを最近直したりしてたよ、みたいなお話でした。 Fiberはコルーチンやサブコルーチンの機能を実現できるので、個人的には結構好きだったりします(https://qiita.com/south37/items/99a60345b22ef395d424 みたいに async/await の実装に使えたりするので面白いです)。

How Close is Ruby 3x3 For Production Web Apps

Ruby3x3に向けてどれだけ早くなってるかを調べるために、Rails appを対象にしてbenchmarkをとってみたよ、という話。指標は色々あるけど、http requestを捌くthroughputで1.5倍くらい早くなってるとの事。 会社としてこういう取り組みをしてるみたいで、OSSへのモチベーションが高い会社なんだなーと思いました。

Gemification for Ruby 2.5/3.0

Rubyの標準ライブラリをGemに移行して行ってるよ、というお話。狙いとしては、Ruby本体からライブラリを切り離す事で「Ruby本体はバージョンアップできないけど特定のライブラリだけバージョンアップする」みたいな事をやりやすくしたいらしいです。 個人的には、Gemに移行する際に基本的にgithubにレポジトリを作ってるみたいだったので、外からコードが見えやすくなってコントリビュートのハードルが下がりそうなのが好感触でした。

How to optimize Ruby internal

watsonさんが3月頃からRubyにperformance改善のpatchを送り続けていた際に、どういう狙いでどういった変更を行ってたかを話していました。 自分もちょうどその頃Rubyのコードを読んだりRedmineのIssueを見たりGitHubのPRを見たりしていて、watsonさんの怒涛のperformance improvementのpatchも目撃していたので、どういうモチベーションだったのか聞けて良かったです。

mruby gateway for huge amount of realtime data processing

h2oのmruby handlerの中で外部通信を並列で行いたくて、その辺の処理をうまく記述するためにhttp_requestとFiberを組み合わせて書いてたよ、というお話。 僕の中ではFiberは基本的にloopと組み合わせて使う印象で、そのループがおそらくh2oの管理するイベントループなのが興味深かったです(もしかしたら何か勘違いしてるかも)。

Ruby Commiters vs the World

Ruby Commiter が会場のみんなから質問を受け付けて色々答えるセッションです。 EndohさんがCookpadのフルタイムコミッターになりましたっていうニュースの後で始まり、EndohさんがRubyへ型システムを載せようとしてる事から型の議論が熱かったです。matzさんは型を手で書くのはすごく嫌、どうしても入れるならせめて後から消せる形(コメントにメタ情報として記載)で、と言っていて、強い思い入れを感じました。個人的にはcompile時にstaticに型チェックして欲しい気持ちはあり、その為なら多少記述が増えても良いと思う派ですが、そこをテクノロジーで何とか記述させずに済ませたいという気持ちはわかるなーと言うスタンスです。

懇親会

  • Rubyコミッターの方とたくさん話せました。
  • 以前から話してみたかった人と話せたので、良い体験でした。

Watsonさん

彼の patch を参考にして自分も performance improvement の patch を書いたりしていたので、以前からお話ししてみたかった方でした。どうやって着手する箇所を見つけてるのか気になってましたが、やっぱりコードを端から見ていって直せそうな箇所を直す、というアプローチをとっていたらしいです。(普通のアプリケーションの速度改善なら profile をとってボトルネックを見つけて、という形で performance improvement は行いますが、Watsonさんはばらばらと色々な箇所に着手していたので、profiling とは別のアプローチが必要だよなーと感じていました。)

rheniumさん

自分のpatchのreviewを行なってくれた人で、調べるとすごく若い雰囲気を感じたのでどんな人か気になっていました。話すと、大学3年生らしく、やっぱり若かったです。どういう経緯でRubyコミッターになったのか、みたいな話をしました(openssl本体やopenssl gemにバグがあって修正patchを送っていたら、任命されたらしいです)。

Endohさん

実は2年前のRubyKaigiでお話ししたことがあり、さらに弊社CTOと大学の同級生というちょっとした繋がりもあり、覚えてくださっていて向こうから話しかけてくれました。とても嬉しかったです。Rubyの型システムをどういう形にするかは悩ましいけど、PythonのType Hintsっぽいものが落とし所としてはありえそう、みたいな話をしました。

k0kubunさん

llrbなどが良いアプローチだなーと思っていたので以前からお話ししてみたかった方でした。話しかけたら、向こうも自分を知ってくれていて、嬉しかったです(自分の書いたpatchを彼がスライドで取り上げてくれたことがあって、そこで認知してくれていました)。 Rubyを根本的に早くするにはJITやその中での様々なoptimizeが必要なはずで、whileみたいなキーワードは扱いやすい方だけどeachみたいなメソッド呼び出しのループは難しいよね(blockのinline化やメソッド再定義された時のdeoptimizeが必要)って話をしたら、「VradがJITに着手していて、『2ヶ月後にはCRubyのJITが作れる』らしいよ」と言っていました。すごいw Vradimir MakarovさんはRuby 2.4で内部のhash table実装高速化もしていてすごい人なので、期待したいです。

2016年振り返りと2017年に向けて考えている事

あけましておめでとうございます。気がつけば2016年もあっというまに過ぎ去り、2017年になりました。

新年明けたばかりで良い機会なので、2016年にどういう事をしたか、どういう事を考えていたかを振り返った上で、2017年に何をしていきたいか考えてみたいと思います。

2016年の仕事の振り返り

まずは仕事面での振り返りです。

僕は2015年4月から新卒のソフトウェアエンジニアとして働き始めたので、2016年は2年目として過ごす事になりました。

取り組む内容として「ソフトウェア開発というアプローチで『サービスを作る』」という部分は変わりません。ただ、2年間働いて積み重ねてきた事の結果として、取り組む内容や責任を持つ範囲が広がった様に思います。

2016年に取り組んでいたのは、主に「新規サービスの立ち上げ」や「小さく始まったサービスをリニューアルして本格的に始動させる」といった事で、エンジニア2人程度の小さなチームではあるものの、「チームのリーダー」として働く様になりました。

ここで「チームのリーダー」と表現したのは、サービスを開発するチームの技術的選択と人事的な評価に責任を持つのが求められる役割で、いわゆるテックリード+エンジニアリングマネージャーみたいなポジションです。初めての経験なのでどんなものかと思いつつ、最近はこの辺の話題がRebuild.fmのおかげでいろいろ盛り上がっていて参考になる情報も多かったので、手探りながらも取り組んでいました。

その他、弊社では会社の文化として「サービスの成長の為の"取り組み"にもエンジニアが責任を持つ」様にしているのですが、そこにはいつも難しさを感じています。弊社では、開発する機能や施策の決定、その効果に対してエンジニアが責任を持ち、サービスの成長を評価するための数字を目標として設定します。このあたりの取り組みは、過去に別のブログにもまとめました。目標に向けてのアプローチを自分で考える為、やりがいや責任感を強く感じる一方、より良い取り組みは無いだろうかと常に頭を悩ませる事にもなります。アイディアなども重要になって来る上に正解は無く、自由と責任はセットだなーと常に感じています。

「意思決定」という言葉はよく聞くものの、それに伴う「責任」について最近は考える様になりました。

2016年のプライベートの振り返り

プライベートを振り返ると、2016年はずっと本を読んだりコードを読んだりしていた様に思います。

僕はHajime Moritaさんという方を勝手に一方的に尊敬していて、彼のブログやツイート、Podcastでの発言をいつもありがたく読んだり聞いたりします。その中でも彼のRebuild.fm ep127に置ける「実装のアイディア(最適化のアイディア)はOSやプログラミング言語RDBみたいな昔から研究されてるソフトウェアの実装から盗める」発言を聞いて以来、コードを読むことに対するモチベーションが増しました。これが、本を読んだりコードを読んだりする事に専念していた主な理由の様に感じます。

備忘録も兼ねて、2016年に興味を持ったトピックをリンク付きでまとめて見たいと思います。(どうでも良いコメントですが、自分が読んでいた本や文章を振り返ってみたら、自分の興味の変遷が分かって面白かったです)

プログラミング言語処理系の実装

プログラミング言語処理系には昔から興味があり、言語処理系作成について記述した書籍(言語実装パターンコンパイラ―原理・技法・ツールなど)を興味ある部分だけつまみ食いしたり、特定の言語処理系について記述した書籍(Ruby under a microscopeなど)を読んだりしていました。

また、オンラインの媒体としては、48時間でSchemeを書こうLambda Calculus - Write You a Haskelを写経してみたり、8ccのcommitを最初から追いかけて写経してみたりしていました。

Parser の実装

プログラミング言語処理系の実装方法の中でも、自分の中で特に興味があったのは「Parser の実装方法」です。JSONSQL、汎用プログラミング言語などソフトウェアの至る所でParserは必要になる(情報を表現するにはその情報を表現する為のフォーマットとそのフォーマットから情報を取り出せるParserが必要になる)ものの、ほとんどの場合には既存の実装を用いて済ましてしまう為、自分で興味を持たない限り「どう実装されてるかを知る機会が無い」と感じていました。重要性の割に、自分はちゃんと仕組みを理解してないと感じたのです。

yaccの文法は昔勉強した事があったのですが、「yaccの使い方」が分かっただけで、内部で何をしてるか、あるいは他の方法が無いのかなどが気になってました。

という訳で書籍を読んだりコードを読んだりしてた訳ですが、結果として自分の中で知識が整理されて、すごく良かった様に思います。

まず、「文法」と一言で言っても、その文法のParserの作りやすさ、実行時間はその「文法」に依存します。文法が許すなら、LL(1)再帰下降Parserの様な「入力文字列長に対して線形の実行時間で処理できる」Parserを作ることができます。LL(1)再帰下降Parserはまた、1字先読みでdispatchすれば良いのでコードも読みやすく、手で書くのも簡単だったりします(JSON Parser くらいなら、自分で書く事も簡単にできます。まあ、僕の実装はmatchの判定しかしない&色々バグはあるんですが。。。)

一方、複雑な文法になると「固定長先読み再帰下降Parser」では次にmatchする文法規則は決定出来ず、matchを試して失敗したらバックトラックしてまた別の文法規則でのマッチを試して、、、といった動作が必要になります。この様にバックトラックが入ると、メモ化などをしない限り実行時間が入力文字列長に対して 指数関数的 に増大し、実装も複雑になります。その為、文法をどう設計するかはparserの実装に対して重要な意味を持ちます。

再帰下降Parserもバックトラックなどが入ると自分で一から書くのは大変になる為、parser generatorを利用したり、parser combinatorなどのライブラリを利用したりします。また、ボトムアップなparseを行う手法(LR法)もあったり、その為のparser generator(yacc など)を利用したりも出来ます。

parser generatorが何をやってるか、また自分でparserをイチから書くならどう書くか、parseが簡単な文法というのはどういったものか、parserを書く為に利用できるツールやライブラリにどういったものがあるか、といった事について自分の中で知識が整理されたので、スッキリしました。

正規表現エンジンの実装

正規表現エンジンの実装は昔から興味があったのですが、正規表現技術入門 がすごく勉強になりました。オートマトン理論ベースの実装とVMベースの実装の概念とコードがどちらも詳しく解説されていて、読むと正規表現エンジンに対する理解が深まりました。

計算理論の話

Parserや正規表現エンジンの勉強をしていたらだんだんオートマトンチューリングマシンに対してしっかりした理解をしておきたいと考える様になり、一時期計算理論の基礎を読んでいました。個人的に一番良かったのは非決定性に対する理解が深まった事だと思います。以前までNPの説明がイマイチピンと来てなかったのですが、非決定性チューリングマシンの動作やツリー状の探索パスがイメージできる様になった事で、しっくり来る様になりました。

変化に強いシステムを作る方法

仕事をする様になると「大きなコードベースに触れる機会」が増加し、コードを整理して「変化に強い状態を保つ重要性」を実感する様になりました。その為のテクニックには様々なものがありますが、特に同僚にオススメされたオブジェクト指向のこころという書籍が「デザインパターンというアプローチで変化に強いシステムを作る方法」を大変わかりやすくまとめていて、良い本だなーと思いながら読んでいました。個別のパターン以上に、「インターフェース・集約の利用、流動的要素のカプセル化」みたいな原則とその理由がまとまってるのが良かったです。

Concurrency

ムーアの法則の終焉が噂される現代において、Concurrencyの重要性は高まり続けています。しっかりと理解しておきたいと考えて、Concurrencyにも興味を持っていました。

Concurrency を実現しようと考えた時、最も一般的な方法はthreadを利用する事です。特にマルチコアを並列で動かそうと思うとカーネルthread(ここではgreen threadと違いカーネルにschedulingされるthreadという意味でこの用語を用いています。Unixであればpthreadを意味してます。)の利用が必要で、pthreadの利用方法についてインターネットサーバでのPthreadとepollPthreadsプログラミングを読んだりしていました。

また、その他のConcurrencyのプリミティブ、特に有名なのはEarlangのアクターやGoのgoroutineですが、それぞれの利用方法に加えて、どう実現されているのか、特にschedulerの実装がどうなっているかを解説した記事(How Erlang does schedulingThe Go scheduler)を読んだりもしてました。どちらもカーネルthreadをうまく利用してマルチコアを活用してくれるので、とても便利な道具だと思います。data raceやrace conditionといったthread programmingの複雑さに生身で立ち向かうのは辛いので、これらの抽象化はうまく活用したいです。

ちなみに、concurrency primitiveには他にも色々なものが存在しているらしく、Concurrent Programming for Scalable Web Architecturesの5章が良い感じにまとまっていました。通して読めてはいないですが、興味深いと思ってます。

分散システム

コアレベルでの並列化に加えて、マシンレベルでの並列化の重要性も高まっています。計算リソースの確保という意味ではHadoopやSparkが、またデータベースの地理的な分散や可用性の確保、書き込みのスケーラビリティの実現という意味ではCassandraなどがオープンソースの分散システムとして注目されていると思います。

自分はkuenishiさんのブログを読んで分散システム自体には興味を持っていたものの、具体例を知らないためにイマイチ理解できていませんでした。そこで一念発起してCassandraを読んで見たのですが、これがとても良い本でした。

まず、自分の中であやふやだった知識が明確になりました。結果一貫性、因果一貫性、強一貫性といった用語の明確な定義(読み込み時に、最新の書き込み結果を反映している事を保証するかどうかが違う)、CAP定理が意味する事、Cassandraがネットワーク分断時にどういった動作をするのか、コントロール可能な一貫性とはどういう事か、そういった事について理解を深める事ができました。それらはまた、分散システムの複雑さに Cassandra がどう立ち向かっているかについての理解でもあって、具体的な例を知れたのはとても良かったです(今後、別のシステムの説明を見たときの比較対象になるので)。

ちなみに、Cassandraは他のNoSQLや内部の細かいアルゴリズムの説明もしたりしていて、内容がとても充実していたのも魅力的でした。

その他、興味深かった本

Unix考古学という本を気まぐれで読んでいたのですが、これがかなり面白かったです。UnixC言語が生まれる時代的背景も興味深いですし、Unixベンダーが1980年代後半に争っていた話なども噂でしか知らなかったので面白かったです。

ピクサー流 創造するちからという本もかなり良かったです。これは、ピクサー、ディズニー社長のエド・キャットムルが映画制作というクリエイティブな作業を行うチームをどう作りあげてきたか、またどういう取り組みをしてきたかをまとめた本なのですが、エドが「常によく考え続けてる」ことを強く感じる本となっています。

個人的に強く印象に残ったのは、「ピクサーで作られるどんな映画も、作り始めた段階では例外なく駄作」という話です。彼らは毎回挑戦をするからこそ最初はひどい出来で、しかしそこから何度も何度も修正を加え続けるからこそ「素晴らしい映画」を作り上げられる事、それを経験からくる実感と共に語っているのが興味深かったです。映画制作の最中には「どうしようもないと行き詰まるタイミングが必ずやって来る」というのも、それを何度も経験して乗り越えてきたからこそ言える事だと思います。その為のプロセスを確立していて、プロセスやチームを信じられるというのもすごい話だと思いました。

2016年振り返りまとめと2017年の取り組み

2016年は「知りたい事、興味のある事についてちゃんと理解を深めよう」と思って過ごしていました。それはそれで学ぶことが多くて良かったのですが、一方で本を読んだりコードを読んでそのまま満足してしまうケースが多すぎた様に感じています。

2017年は、コードを書く事、特にそれをpublicにする事を強く意識していきたいと思っています。OSSへの貢献などは、興味がありつつも全く出来てない分野なので、取り組みたいと思っています。

仕事面では、取り組んでる内容に習熟することに加えて、「責任」というものとの付き合い方にも慣れていきたいと思っています。

2015年、2016年に買った技術書105冊

僕は技術書を買ったり読んだりするのが好きです。昨年4月からソフトウェアエンジニアとして働き始めて、学生の頃に比べると経済的に余裕が出来たため、技術書を買うペースが飛躍的に上昇しました。

もはや自分でも何を持っているのか、何冊持っているのかが分からなくなってきていたので、リストアップして数えてみました。

数えた結果

2015年、2016年に買った本は105冊でした。以下がその内容です。思ったよりも多かったです。

並べてみるとなかなか面白くて、同一ジャンルのものも何冊か買ってます。同じものについての説明でも別の観点があったり、あるいは説明の分かりやすさ自体が異なったりするので、個人的には意味があるんじゃないかと思ってます。

積読もあるので、今後も読み進めて行こうと思っています。

2015, 2016年に買った技術書

Effective Ruby

Effective Ruby

Webエンジニアが知っておきたいインフラの基本

Webエンジニアが知っておきたいインフラの基本

[24時間365日] サーバ/インフラを支える技術 ?スケーラビリティ、ハイパフォーマンス、省力運用 (WEB+DB PRESS plusシリーズ)

[24時間365日] サーバ/インフラを支える技術 ?スケーラビリティ、ハイパフォーマンス、省力運用 (WEB+DB PRESS plusシリーズ)

ハイパフォーマンス ブラウザネットワーキング ―ネットワークアプリケーションのためのパフォーマンス最適化

ハイパフォーマンス ブラウザネットワーキング ―ネットワークアプリケーションのためのパフォーマンス最適化

プログラマのためのサバイバルマニュアル

プログラマのためのサバイバルマニュアル

Haskellによる並列・並行プログラミング

Haskellによる並列・並行プログラミング

詳解 OpenCV ―コンピュータビジョンライブラリを使った画像処理・認識

詳解 OpenCV ―コンピュータビジョンライブラリを使った画像処理・認識

新装版 リファクタリング―既存のコードを安全に改善する― (OBJECT TECHNOLOGY SERIES)

新装版 リファクタリング―既存のコードを安全に改善する― (OBJECT TECHNOLOGY SERIES)

詳解 Linuxカーネル 第3版

詳解 Linuxカーネル 第3版

Amazon Web Services実践入門 (WEB+DB PRESS plus)

Amazon Web Services実践入門 (WEB+DB PRESS plus)

make 改訂版 (A nutshell handbook)

make 改訂版 (A nutshell handbook)

コードコンプリート―完全なプログラミングを目指して (Microsoft PRESS)

コードコンプリート―完全なプログラミングを目指して (Microsoft PRESS)

オブジェクト指向のこころ (SOFTWARE PATTERNS SERIES)

オブジェクト指向のこころ (SOFTWARE PATTERNS SERIES)

計算理論の基礎 [原著第2版] 1.オートマトンと言語

計算理論の基礎 [原著第2版] 1.オートマトンと言語

計算理論の基礎 [原著第2版] 2.計算可能性の理論

計算理論の基礎 [原著第2版] 2.計算可能性の理論

計算理論の基礎 [原著第2版] 3.複雑さの理論

計算理論の基礎 [原著第2版] 3.複雑さの理論

Unix考古学 Truth of the Legend

Unix考古学 Truth of the Legend

オブジェクト指向における再利用のためのデザインパターン

オブジェクト指向における再利用のためのデザインパターン

言語設計者たちが考えること (THEORY/IN/PRACTICE)

言語設計者たちが考えること (THEORY/IN/PRACTICE)

全面改訂版 はじめてのGTD ストレスフリーの整理術

全面改訂版 はじめてのGTD ストレスフリーの整理術

Binary Hacks ―ハッカー秘伝のテクニック100選

Binary Hacks ―ハッカー秘伝のテクニック100選

Debug Hacks -デバッグを極めるテクニック&ツール

Debug Hacks -デバッグを極めるテクニック&ツール

はじめてのOSコードリーディング ~UNIX V6で学ぶカーネルのしくみ (Software Design plus)

はじめてのOSコードリーディング ~UNIX V6で学ぶカーネルのしくみ (Software Design plus)

ソフトウェアの世界でキャリアを築く Making it Big in Software

ソフトウェアの世界でキャリアを築く Making it Big in Software

Effective Modern C++ ―C++11/14プログラムを進化させる42項目

Effective Modern C++ ―C++11/14プログラムを進化させる42項目

正規表現技術入門 ――最新エンジン実装と理論的背景 (WEB+DB PRESS plus)

正規表現技術入門 ――最新エンジン実装と理論的背景 (WEB+DB PRESS plus)

Hacking: 美しき策謀 第2版 ―脆弱性攻撃の理論と実際

Hacking: 美しき策謀 第2版 ―脆弱性攻撃の理論と実際

型システム入門 −プログラミング言語と型の理論−

型システム入門 −プログラミング言語と型の理論−

  • 作者: Benjamin C. Pierce,住井英二郎,遠藤侑介,酒井政裕,今井敬吾,黒木裕介,今井宜洋,才川隆文,今井健男
  • 出版社/メーカー: オーム社
  • 発売日: 2013/03/26
  • メディア: 単行本(ソフトカバー)
  • クリック: 68回
  • この商品を含むブログ (11件) を見る

Pthreadsプログラミング

Pthreadsプログラミング

きつねさんでもわかるLLVM ~コンパイラを自作するためのガイドブック~

きつねさんでもわかるLLVM ~コンパイラを自作するためのガイドブック~

Sparkによる実践データ解析 ―大規模データのための機械学習事例集

Sparkによる実践データ解析 ―大規模データのための機械学習事例集

Linuxカーネル2.6解読室

Linuxカーネル2.6解読室

アジャイルソフトウェア開発の奥義 第2版 オブジェクト指向開発の神髄と匠の技

アジャイルソフトウェア開発の奥義 第2版 オブジェクト指向開発の神髄と匠の技

プログラミングErlang

プログラミングErlang

すごいErlangゆかいに学ぼう!

すごいErlangゆかいに学ぼう!

UNIXシステム管理 第3版〈VOLUME 1〉

UNIXシステム管理 第3版〈VOLUME 1〉

UNIXシステム管理 第3版〈VOLUME2〉

UNIXシステム管理 第3版〈VOLUME2〉

UI GRAPHICS ―世界の成功事例から学ぶ、スマホ以降のインターフェイスデザイン

UI GRAPHICS ―世界の成功事例から学ぶ、スマホ以降のインターフェイスデザイン

  • 作者: 水野勝仁,深津貴之,渡邊恵太,菅俊一,緒方壽人,iA,鹿野護,森田考陽,庄野祐輔,塚田有那
  • 出版社/メーカー: ビー・エヌ・エヌ新社
  • 発売日: 2015/12/17
  • メディア: 単行本
  • この商品を含むブログ (2件) を見る

Hadoop 第3版

Hadoop 第3版

ZooKeeperによる分散システム管理

ZooKeeperによる分散システム管理

アート・オブ・プロジェクトマネジメント ―マイクロソフトで培われた実践手法 (THEORY/IN/PRACTICE)

アート・オブ・プロジェクトマネジメント ―マイクロソフトで培われた実践手法 (THEORY/IN/PRACTICE)

マイクロサービスアーキテクチャ

マイクロサービスアーキテクチャ

プログラマのための文字コード技術入門 (WEB+DB PRESS plus) (WEB+DB PRESS plusシリーズ)

プログラマのための文字コード技術入門 (WEB+DB PRESS plus) (WEB+DB PRESS plusシリーズ)

4.4BSDの設計と実装

4.4BSDの設計と実装

  • 作者: マーシャル・カークマキュージック,マイケルカレルズ,キースボスティック,ジョンクォーターマン,Marshall Kirk McKusick,Michael J. Karels,Keith Bostic,John S. Quarterman,砂原秀樹,七丈直弘
  • 出版社/メーカー: アスキー
  • 発売日: 2003/09
  • メディア: 単行本
  • 購入: 4人 クリック: 9回
  • この商品を含むブログ (13件) を見る

プログラミング作法

プログラミング作法

並行コンピューティング技法 ―実践マルチコア/マルチスレッドプログラミング

並行コンピューティング技法 ―実践マルチコア/マルチスレッドプログラミング

Coders at Work プログラミングの技をめぐる探求

Coders at Work プログラミングの技をめぐる探求

コンパイラ―原理・技法・ツール (Information & Computing)

コンパイラ―原理・技法・ツール (Information & Computing)

言語実装パターン ―コンパイラ技術によるテキスト処理から言語実装まで

言語実装パターン ―コンパイラ技術によるテキスト処理から言語実装まで

マスタリングNginx

マスタリングNginx

みんなのGo言語[現場で使える実践テクニック]

みんなのGo言語[現場で使える実践テクニック]

Go言語によるWebアプリケーション開発

Go言語によるWebアプリケーション開発

Rubyのしくみ -Ruby Under a Microscope-

Rubyのしくみ -Ruby Under a Microscope-

DNS & BIND 第5版

DNS & BIND 第5版

実践 パケット解析 第2版 ―Wiresharkを使ったトラブルシューティング

実践 パケット解析 第2版 ―Wiresharkを使ったトラブルシューティング

OpenSSH[実践]入門 (Software Design plus)

OpenSSH[実践]入門 (Software Design plus)

UNIXという考え方―その設計思想と哲学

UNIXという考え方―その設計思想と哲学

シェルプログラミング実用テクニック (Software Design plus)

シェルプログラミング実用テクニック (Software Design plus)

プロダクティブ・プログラマ -プログラマのための生産性向上術 (THEORY/IN/PRACTICE)

プロダクティブ・プログラマ -プログラマのための生産性向上術 (THEORY/IN/PRACTICE)

ビューティフルコード (THEORY/IN/PRACTICE)

ビューティフルコード (THEORY/IN/PRACTICE)

Beautiful Architecture: Leading Thinkers Reveal the Hidden Beauty in Software Design

Beautiful Architecture: Leading Thinkers Reveal the Hidden Beauty in Software Design

SQL実践入門──高速でわかりやすいクエリの書き方 (WEB+DB PRESS plus)

SQL実践入門──高速でわかりやすいクエリの書き方 (WEB+DB PRESS plus)

Rubyを256倍使うための本 無道編

Rubyを256倍使うための本 無道編

世界でもっとも強力な9のアルゴリズム

世界でもっとも強力な9のアルゴリズム

Cassandra

Cassandra

電子書籍で買った本

ワーク・シフト ― 孤独と貧困から自由になる働き方の未来図〈2025〉

ワーク・シフト ― 孤独と貧困から自由になる働き方の未来図〈2025〉

プログラミングElixir

プログラミングElixir

ガベージコレクション

ガベージコレクション

はじめて学ぶソフトウェアのテスト技法

はじめて学ぶソフトウェアのテスト技法

ピクサー流 創造するちから―小さな可能性から、大きな価値を生み出す方法

ピクサー流 創造するちから―小さな可能性から、大きな価値を生み出す方法

エクストリームプログラミング

エクストリームプログラミング

SOFT SKILLS ソフトウェア開発者の人生マニュアル

SOFT SKILLS ソフトウェア開発者の人生マニュアル

オブジェクト指向でなぜつくるのか 第2版

オブジェクト指向でなぜつくるのか 第2版

システムはなぜダウンするのか

システムはなぜダウンするのか

チームが機能するとはどういうことか――「学習力」と「実行力」を高める実践アプローチ

チームが機能するとはどういうことか――「学習力」と「実行力」を高める実践アプローチ

エンタープライズ アプリケーションアーキテクチャパターン (Object Oriented SELECTION)

エンタープライズ アプリケーションアーキテクチャパターン (Object Oriented SELECTION)

ジェフ・ベゾス 果てなき野望

ジェフ・ベゾス 果てなき野望

ビジョナリー・カンパニー ― 時代を超える生存の原則

ビジョナリー・カンパニー ― 時代を超える生存の原則

世界で闘うプログラミング力を鍛える150問 ~トップIT企業のプログラマになるための本~

世界で闘うプログラミング力を鍛える150問 ~トップIT企業のプログラマになるための本~

Apache Kafka入門

Apache Kafka入門

まつもとゆきひろ コードの未来

まつもとゆきひろ コードの未来

入門Ansible

入門Ansible

Redis入門 インメモリKVSによる高速データ管理

Redis入門 インメモリKVSによる高速データ管理

深層学習 (機械学習プロフェッショナルシリーズ)

深層学習 (機械学習プロフェッショナルシリーズ)

イノベーションのジレンマ―技術革新が巨大企業を滅ぼすとき (Harvard business school press)

イノベーションのジレンマ―技術革新が巨大企業を滅ぼすとき (Harvard business school press)

高速スケーラブル検索エンジン ElasticSearch Server (アスキー書籍)

高速スケーラブル検索エンジン ElasticSearch Server (アスキー書籍)

Yコンビネーター シリコンバレー最強のスタートアップ養成スクール

Yコンビネーター シリコンバレー最強のスタートアップ養成スクール

ワーク・ルールズ!―君の生き方とリーダーシップを変える

ワーク・ルールズ!―君の生き方とリーダーシップを変える

ゼロ・トゥ・ワン―君はゼロから何を生み出せるか

ゼロ・トゥ・ワン―君はゼロから何を生み出せるか

内部構造から学ぶPostgreSQL 設計・運用計画の鉄則 (Software Design plus)

内部構造から学ぶPostgreSQL 設計・運用計画の鉄則 (Software Design plus)