如何にしてAsakusaから来た面々はISUCON7の予選に敗北したのか

とてもとても悲しいので、とりあえずやったことと言い訳を書いて気を紛らわせることにする。 敗北した身でグダグダ言うのが格好悪いことは百も承知だが、人間には魂の救済が必要であることをご理解いただきたい。

序盤〜方針決定

最初パスワードのコピペミス等でサーバーからガンガンBANされて、そもそもログインできなくなる。これで10分から20分ぐらい無駄にした気がする。 テザリングにIPを切り替えたり、他のノードから入ったりして、何とか公開鍵でログインできる環境を整える。

適当にベンチ流してスコアを取る前に、nginxのログ設定や構成を確認しalpを使って集計できる準備を整えた。デフォルト実装とRuby実装でベンチを流す。その裏で実装を一通り読む。

f:id:joker1007:20171023022330j:plain

ざっくり図を書いて、相談。とにかく/iconsを何とかしないと話が進まないので、静的ファイルとして書き出してCache-Controlだよね、までは即決。

モリスさんの発案により全てのノードにPOSTが来た時点でPUTリクエストを転送し、WebDAVで全てのノードにファイルを書き出して、後はnginxでサーブすればいいという方針で行こうということになる。この決定は後になって思うと危険な判断ではあった。

そこに多少の準備がかかるので、その間にSQLやアプリケーションの実装周りで明らかに非効率な所を潰すことにした。俺はRubyコードの全般を直し、やんちゃさんにDB周りのインデックスやSQLを見てもらった。

中盤

/iconsの静的ファイル化が完了し、nginxにより直接サーブが可能になる。この時点でスコアが3万前後。画像ファイルのキャッシュとかは一切してないので、周りのスコアとかを見ても、まあこんなもんだろうと思う。

ここで一つ目の壁にぶち当たる。nginxにexpiresを追加してCache-Controlが動作する様にしたのだが、スコアが伸びない。この時点でベンチマーカーが一体何であるのかを考えることになる。

ここで我々のチームは、ベンチマーカーがCDNかキャッシュプロキシの様なものからのリクエストである、ということをすぐに想定できなかった。少なくとも自分はブラウザかAPIのクライアントの様なものしかすぐに想定できなかった。

ただ、ネットワークがサチっていることはメトリックから明らかであり、周りのチームとのスコア差を考えると、304かCache-Controlによるキャッシュしか方法が無いだろうというのは分かっていた。

その間に裏でワーカーの数やらキャッシュを調整し、スコアを45000ぐらいまで伸ばす。やったのは大体以下の様な感じ。

  • チャンネルは作ったら変更されないので、起動時に全部Redisのハッシュにストア
  • チャンネルが保持しているメッセージ数もRedisにハッシュでストアしメッセージが入ったらhincrbyする
  • db.prepareを全てmysql2-cs-bindのxqueryに置き換える
  • RedisとMySQLのコネクションをコネクションプール化し起動時に接続済みにしておく
  • nginxとpumaのプロセス数を2にして、スレッド数やwocker_connection数を調整
  • カーネルのsomaxconnが128で少なかったので数を増やす
  • SQLのクエリワークロードに合わせてインデックスを張る (そんなにやることはなかった)
  • N+1をJOINに変えて潰す

ちなみに、pubsubとか使えそうかなとは考えたが、3台でそれやってもなあというのと、短時間で実装するのが無理っぽかったので止めた。

しばらく悩んだ後にモリスさんが気付いてCache-Controlにpublicを突っ込んだらスコアが倍ぐらいになり、どうもCDNっぽいという話が出てきた。

終盤

Cache-Controlがある程度効いているのだが、やっぱりネットワークがサチってスコアが10万辺りで止まる。304を返して何とかする方法があるはずだ、と思ってパケットキャプチャをしてクライアントの動きを見たのだが、どうもIf-Modified-SinceやらIf-None-Matchが見当たらなかった。(本当は少数ログに残ってた可能性はあるが気付かなかった)

で、どうやって304で返すかで色々と迷走することになる。この時にベンチマークの仕様について確信が持てなかったため、肝心なことに気付けなかった。EtagやLast-Modifiedが入ってて、何故ネットワークが先にサチるのかが分からなかった。

その間も裏でアプリケーションのキャッシュ可能な場所を探したり、nginxのopen_file_cacheやらTCP周りのカーネルチューニングをやって11万ぐらいは安定して出る様になっていた。

しかし、最終的に最後まで304でレスポンスを返すことができず、アプリケーションやDBにかかっている負荷は5割に満たないまま時間切れとなった。

アプリケーションサーバー側に来ていたトラフィックは遅くても100msec、POSTでも200msecぐらいで、半数以上は数十msecで返せていたのでウェブアプリケーションとしては充分な水準だったとは思う。

最終的な敗因

終わった後の情報からの推測によると、一番致命的だったのは静的なファイルを返す様にした際に各ノードに初期画像を撒いたのだが、その時にファイルの更新時間を揃えるのを忘れたという点だと思われる。

ブラウザだったら、Cache-Controlで一旦ローカルにキャッシュされてしまえば、If-Modified-Sinceが多少異なっていても、そもそもサーバーにアクセスしないので、何も問題は無い。

しかし、後から推測するにベンチマーカーはCDNからのリクエストを想定しているものだと思われる。なのでレスポンスヘッダの状態をちゃんとチェックしてキャッシュの削除をしていたんじゃないだろうか。

もし、ファイルの更新時間が異なる同一ファイルが各ノードにあった場合、あるノードから戻ってきたLast-Modifiedが自分がリクエストしているIf-Modified-Sinceより前になる場合、というのが発生する。ここの値が一致しないとnginxはデフォルトでは普通にコンテンツを返すはず。

ここで、一つ気付いていながら確信が持てず試さなかったのが、nginxのif_modified_since beforeである。もしサーバーが持っているファイルの更新時間より未来のIf-Modified-Sinceが送られてきても、nginxは304を返すことができる設定がある。恐らくうちの場合はこれでほとんどのコンテンツに対して304を返すことができた可能性がある。

一方でEtagもレスポンスヘッダに含まれており、ファイルの更新時刻が異なる場合それも異なってしまうので、最終的にはnginxの実装に依る様な気もする。どっちにしても駄目だったかもしれないが、そこまでの知識はない。

何にせよ、上記の問題によって、初期画像に対するリクエストのほとんどが304を返すことができなかった。

そのためネットワークがサチって負荷が上がりきらずスコアが伸びなかった。3台分の帯域をフルに使ってWeb,DB共にリソースの半分以上の余力を残して11万点だったので、304がまともに返せていれば、20万後半から30万ぐらいは行けたんじゃないかとは思うのだが、完全に別の世界線の話になってしまったので、我々には本当のところは分からない……。

ちなみに、WebDAVでファイルを複製して各ノードに配置したことが危険だったのは、ファイルを書き込んだタイミングが1秒以上ズレると上記と同じ問題が発生するところだった。

そもそもファイルの更新時間という点に気付いていなかったので、ここも致命的だったのかどうかは定かではない。ローカルネットワークは帯域もレイテンシも全然余裕であり、書き込みが終わるまでに全体で0.1秒以下ぐらいしかかかってないので、よっぽど運が悪くない限りはそうそうズレることは無いと思っていたのだが、ぶっちゃけ各ノードの時計が秒単位で一致してたかというと、はなはだ怪しい。恐らくこれも影響があったのではないだろうか。

言い訳

実際、適当にいくつかの画像にアクセスした限りでは複数のノードでもEtagもLast-Modifiedも一致していたのも気付けなかった点の一つではある。

しかし、今回私にとってとてもハードルが高かったのは恐らくCDNというものを想定したベンチマーカーだったこと、そしてその挙動特性を知る経験が無かったことだ。

一応、数年Webに関する仕事をしてきて、今CTOなんぞをやっている訳だが、CDNが必要になったことなど今迄一度も無かった。ずっとB2Bで仕事をしていたのでPOSTの数が多いとかやたら複雑だとか一回のGETでめちゃめちゃ複雑な計算結果を返さなきゃいけないことは一杯あるのだが、GETはそんなに世界のあちこちから来ないし、1分に数件とか処理できれば余裕な仕事がほとんどだった。

というわけで、CDN等は遥か遠い世界の話だった。一応メルカリの事件とかは知ってて、ああやべえなCache-Control周り、とかは思ってはいたのだが、所詮対岸の火事であるという認識で、必要になった時に調べられる様に覚えておこう、ぐらいのものだった。

この辺りのハイトラフィックWebに対する地力の無さが敗因だったと言える。

一方で、運が悪かったというか問題の特性によって敗北した点もあると思っている。いくらいきなり無茶なパフォーマンス改善が降ってきたとして、そのサービスがCDNを使っているかどうかと、どういうCDNを使っているかの情報すら無いままサーバーサイドの改善にかかることはまずあり得ないだろうと思う。(まあ、この業界は想像の斜め下とか余裕で越えてくるので分からんけど)

またCDNの導入がされててS3やGCSに類するオブジェクトストレージが使えないというのも、イマイチ考えにくい。今回、ローカルのファイルシステムから画像をサーブした結果ファイルの更新時刻の罠にハマってしまったが、仕事で関わったサービスで画像をサーブするのにローカルのファイルシステムを使ったことは多分一度もなかったと思う。CDNを使うぐらいまで成長したサービスが、そういう環境が無いってのはそんなに多くはないだろう。(オンプレで開発してきて場当たり的な改善とCDNでギリギリ何とかしながら成長してしまったサービスとかならあり得ないとも言えない気はする)

というわけで、今回の問題は本当に世界レベルからのアクセスがあるB2CのハイトラフィックWebと向き合ってきた人間がやはり有利だったと思う。まあ、それがWebサービスの現実であり地力の違いである、と言われればグウの音も出ないのだが……。あー辛い……。

今回の我々のチームは全員がB2B業であり、ミドルウェアやら集計SQLやら分散処理システムやらワークフローを見るのがメインみたいな人間ばかりで、これは完全に最近のWebの現実というものに立ち向かえていなかったと言える。CDN使っててS3の無い世界なんて知らねえよww

まあ、私の様な人間はクラウドのぬるま湯に漬かって生きているのだなあ、ということを実感した1日ではあった。

今回得た教訓は、CDNの仕様は厳密に確認しなければならないということと、ローカルファイルシステムからコンテンツをサーブする時はファイルの更新時間を揃えなければいけない、ということだ。まあ後者の知見はよっぽどでないと使う機会は無さそうだが。(未来のISUCONとかぐらいっぽい)

いやー、S3って本当便利ですよね。

データ分析基盤構築入門の献本をいただいた

先日、著者のデータ分析基盤構築入門の著者の一人である@yoshi_kenさんより、献本をいただきました。

http://gihyo.jp/book/2017/978-4-7741-9218-5

f:id:joker1007:20171006045932j:plain

この本は、Fluentdと、ElasticSearch, Kibanaを中心にしたデータの可視化と分析を行える基盤を実際に構築する手順やその意義等が詳細に書かれた本です。

少し遅くなってしまったのですが、やっと一通り目を通すことができました。

序盤はデータ分析を行うことの意義や、分析を行うためのデータ設計、ETLやデータフローの構築が何故必要なのか丁寧に解説されています。最近私も似た様な分野で仕事をしているので、その通りだなあと頷くことが多い内容でした。

中盤はfluentdの解説、後半はElasticSearchとKibanaについての解説が中心です。かなりconfigサンプルが多いので始めてこういうミドルウェアを触る人にとっては助けになる内容だと思います。

fluentdはv0.12系で書かれていて、現在でも安定板はまだ0.12系の扱いですが、ちょうどv0.14系への移り変わり時期と被ってしまっているのが、残念な所です。軽くフォローはされていますが、基本的な内容はv0.12系をベースに書かれています。私も技術書を書いたことがあるので想像できますが、こういうバージョン移行期の執筆は書く側としてももどかしい思いをする所だと思います。しかし、ほとんどの内容はそのまま活用できますし、fluentdのアーキテクチャや構成パターン、運用TIPS等、幅広く網羅されていて、とても良い内容でした。

そして、最後にAppendixとしてfluentdのプラグインまとめとembulk, digdagについての解説があるんですが、Appendixが異様に分厚くて、これは普通にパート1つ分ぐらいある様なボリュームでしたw 多分、日本語の書籍でfluentd, embulk, digdagについてまとめて解説してる本は貴重だと思います。

embulkの解説の中で、私が作ったembulk-filter-ruby_procを活用している例が紹介されていて、なるほど、ちゃんと誰かの役に立ってるんだと嬉しくなりました。ご紹介いただきありがとうございます!

プラグインまとめでは、私がメンテしてたり作ったりしているプラグインもいくつか紹介されています。この本を読んだ人にとって使えそうなものがあったら幸いですね。

私の仕事でも、fluentdやembulkはかなり活用しており、この本のfluentdの解説はとても手厚いので同僚にオススメしたい感じでした。

今回は、献本していただきありがとうございました!

(そういえば、技術書の献本をいただいたのは初めてかも)

RubyKaigi 2017の記録

先日、広島で開催されたRubyKaigi 2017に行ってきました。

相変わらず各トークのテクニカル度合いが異常にハイレベルで刺激的なカンファレンスでした。

最近、静的解析やRubyと型の関係がホットトピックであることもあり、ripperやparser gem等のRubyパーサやRubyVM::Iseq周りを触っているスピーカーが多く、コアに突っ込んでいく人のアクティビティにはとても刺激を受けました。 個人的にはIseqのバイナリ表現とソースコードの変換を活用してマクロの様なことを実現していたCompiling Rubyという発表が印象的でした。 後、毎年ラストのキーノートはやってることが凄過ぎて、圧倒されるばかりですね。

私自身は、メインのスピーカーとして登壇することはできませんでしたが、LTスピーカーとして話をする機会がもらえたので、そこで登壇してきました。

f:id:joker1007:20170927024108j:plain From RubyKaigi 2017 | Flickr

壇上から写真が撮れるのは嬉しい。 f:id:joker1007:20170919174020j:plain

内容は、Refinementsの貴重なユースケースと、Refinementsにbinding_ninjaという拙作のgemを組み合わせた黒魔術の例を示す、という話でした。

binding_ninjaは、C Extensionとして実装することで、メソッドの呼び出し元のコンテキストのbindingを暗黙的に引数に組み込んで渡す、というgemです。 何のことやら良く分からんと思うので、リンク先のREADMEを読むとどういうものか伝わるかと思います。 binding_of_callerという有名なgemがあるのですが、それの機能限定、高速化版みたいなものです。

後から聞いた感じだと、喋りの勢いと技術的なマニアックさが良い按配だったらしく、割と好評だったみたいです。いやー、ウケて良かったー……。

また、2日目の夜は多くのDrink upが開催されてましたが、私は永和システムマネジメント様がスポンサードしていたDrink upでスタッフとして日本酒の選定をさせてもらいました。

日本酒を大量に準備してのDrink upは二度目で、前回もとても好評だったことや、永和というネーミングバリューもあり、一般参加者の募集は即日完売だったらしく、いやースタッフで良かったーと思いましたね。

RubyKaigi 2日目で「Food, Wine and Machine Learning: Teaching a Bot to Taste」というタイトルで登壇していたMai Nguyenさんが参加してくれて、ワインを愛する彼女に日本酒を振る舞うことができたことを嬉しく思っています。

Drink upも好評に終わって最高の夜でした。

f:id:joker1007:20170919185609j:plain f:id:joker1007:20170919185615j:plain

今回、お店側のスタッフの人がかなりサポートしてくれて、同じグループの日本酒バルのお店からメンバーを派遣してくれた様で、お酒を振る舞う上でめちゃくちゃ助かりました。ちゃんと味を見た上で分かり易くグルーピングして並べてくれたし、好みの味に対するお酒のリコメンドもしっかり応えてくれました。

名刺を貰ったので、もしまた広島に行く機会があれば、是非足を運びたいお店ですね。

f:id:joker1007:20170927180620j:plain

その後、Ruby Karaokeまで参加し、大体最後まで居たんですが、ここでめちゃくちゃ消耗して3日目のセッションの半分以上を聞きそびれるという失態を犯すことに……。 まあその後、海外から来てRuby Karaokeに参加してくれた人に軽くお礼の言葉を貰ったんで、まあいいかーという気になりました。救われた感じw

結局、3日目の夜も大体朝方までデカ外人(@dekagaijin)パークで飲んでいて、ヘロヘロのまま宿に戻ったら、チェックアウトが10時だったので9時ぐらいに起きる羽目になり、ロクに広島観光をする余力もなく、お好み焼きだけ食べて東京に戻る、という感じでした。 本当は、もうちょっと宮島ぐらいまで行ったりしたかったんですが、家まで帰り着いた時の自分のコンディションを考えると、帰って正解だったな、と思う。

来年は仙台ということで、東京からだと広島より行き易いし、ジョジョの聖地である杜王町についにRubyKaigiが!って感じなので、何とかCFPに応募できるぐらいは頑張りたいと思います。

穴子飯美味かった。 f:id:joker1007:20170918213147j:plain

穴子刺とハモとメゴチ。ハモは西日本に限る。 f:id:joker1007:20170918202018j:plain

辛いのはそんなに得意ではないが山椒は好きなので、広島の汁なし担々麺は良かった。 f:id:joker1007:20170918120329j:plain

私的リモートワークの良い点、悪い点

Twitterでちらっと見かけたので、自分も良い点と悪い点をまとめてみようと思う。

良い点

  • 電車に乗らなくて良い
  • ミーティング開始の5分前まで寝てられる
  • 人の話し声がしない
  • 話しかけられずに済む
  • 疲れたらいつでもベッドにダイブできる
  • ちゃんとアウトプットしてれば、仕事している様に見せなくてもいい
  • 寝間着で仕事ができる
  • ハイスペックなPCが使える
  • WiFiが不安定みたいなトラブルが少ない
  • 良い椅子が使える
  • ヘッドホン無しで音楽が聞ける
  • いきなり歌い出しても、誰も変な目で見ないし、迷惑がかからない

基本的に引き篭りなので、自宅の環境が快適になる様に腐心した結果、大抵のオフィスより自宅の方が執務環境として優秀であり、自宅より仕事に関する物の水準が高い会社というのをほぼ見たことがない。

そして、日常生活において、歌うというのが精神の健康上とても大事なので、音楽を聞きながら突然歌い出したりしたいのだが、出社してそれをやると頭が致命的な人に思われてしまうし人に迷惑がかかるので、これが最も重要と言えるかもしれない。 カーレンジャーのOPとか聞いてたら「レッツゴー!」とか言いたいし、キングゲイナーのOP聞きながら「キング、キング、キングゲイナー」って歌わずに済ます方が難しい。(そんな曲を仕事中に聞くな、という話であるが……) 実際、すげー辛いテストコードの修正作業とか無意識で歌えるテンション高めの曲とか歌いながら無理やりドライブすると、結構進捗するので勢いってのは大事だと思う。

悪い点

  • チームメンバーとのコミュニケーション量は減る
  • たまに飲みにいく話になった時に、場所が渋谷とか新宿だと行くのが面倒くさい
  • ギリギリまで寝てようと調整し過ぎて寝坊する、疲れたので仮眠を取ろうとして寝過ぎる
  • 生活リズムが無限にズレていく
  • 仕事を止めるタイミングが無いので無限に仕事をしてしまう
  • 飯を食わなくなり、アルフォートで生活する様になる
  • 運動不足が加速する
  • 職場までの距離に対する我慢が足りなくなってくる
  • 歌いながら仕事をすることに慣れてしまい、たまに外に出た時に突然歌い出す危険が増す

一番問題なのは仕事し過ぎではないかと思う。中断するタイミングも特に無いので飯を食うのが面倒臭くなり、冷蔵庫にストックしてあるアルフォートに頼ることになる。幸いにして家の近くにタリーズがあるので、考えごとやら軽く本読む時にタリーズまで行ってついでにサンドイッチ食ったりする様にしている。

生活リズムのズレを是正する仕組みも無いので、自分の睡眠傾向だと生活リズムがえらいことになる。最近は朝の7時から8時に寝て12時から14時に起きることが多い。半年前ぐらいまでは5時には寝れてたんだが……。そして、ミーティングに合わせて無理やり起きたりするので、かなり辛いことになる。

総じて肉体にじわじわダメージが蓄積されていく。自分がどうしても不健康な生活に向かっていくからなのだが、意思の力とかではどうしようもない感じ。

しかし、基本的に肉体にダメージが溜まるのは根本的に自分の体質やら生活スタイルの問題であり、大なり小なり出社してても同じことなので、仕事をするという点においては、やはり自宅が快適なのであまり自宅から離れたくはない。

Ryzenで久々にPCを1台組んだ

Thinkpadが唐突にぶっ壊れたため、自宅のPC環境を早急に何とかしないと色々不便でしかたなくなってしまった。 最近、Ryzenが盛り上がってるし、ここ5年ぐらいデスクトップPCを新調していなかったので、もうこのタイミングで1台作ってしまうことにした。

ちなみに、予算に限界があったため、タイミング的にThreadripperで組むことも可能だったがそれは諦めた。

構成

パーツ 名称
CPU Ryzen 1800X
マザー MSI X370 GAMING PRO CARBON
メモリ Crucial Ballistix 16GB x2
NVMe CFD CSSD-M2O512PG1VN 512GB
VGA GIGABYTE GeForce® GTX 1070 G1 Gaming 8G
電源 Seasonic X Series 860W SS-860XP2S
クーラー Corsair H110i (簡易水冷)
ケース Thermaltake Core v4l

f:id:joker1007:20170822041403j:plain

所感

ツクモで安売りしてた電源とマザーとRyzenのセットを買って、後は適当に集めた。 大体、これで25万ぐらいか。 再利用できるものが何も無かったんで、全部買い集めたら結構かかってしまった。 割とかかってしまったので、GPUは日和ってGTX 1070にした。まあどうせそんなに激しく使わないだろうし。 ケースを持ち帰る時に、あんまりでか過ぎると重くて辛いので、程々のサイズのミドルタワーにしたら(それでも持ち帰るのは辛かった)、ビデオカードが3.5インチベイに干渉する問題があった。幸い取り外しが効くもので、3.5インチベイにそんなHDDを突っ込む予定も無かったので、ベイを取り外して事なきを得たが、ちゃんと長さを測っとくべきだった。最近のビデオカードがあんなでかいとは……。

OSはもちろんGentooを入れた。

ちなみに、Gentooなので日々バリバリコンパイルしているが、噂のSEGVは起きてない。やっぱあれ初期ロットの問題かBIOSがこなれてなかっただけなんじゃないだろうか。 AGESA 1.0.0.6 ファームウェアならメモリコントローラーがかなり安定する、という話があったのでちゃんとBIOSを上げておけば大丈夫な気がする。

ただ、問題が無かった訳ではなくて、唐突にPCがフリーズする問題に数日悩まされた。 ログにも何も出てなかったのだが、ある日syslogにrcu_schedでCPUがstallしているというログが出てたことと、フリーズする状況が長時間のアイドル後に操作しようとした時に頻発してたことから、色々ググってみるとC6-Stateを切ると安定したという報告が見つかった。 いわゆる、CPUのアイドル時の省電力機能だ。 状況やエラーログから、これはC6-Stateからの復帰に失敗している可能性がかなり高いとみて、BIOSで無効にしてみたところ、めちゃめちゃ安定した。 その後は一度も固まってないし落ちてない。超快適。 ハードウェアの初期不良とかでなくて良かった。CPUが悪い可能性はあるが、別にC6-State切った所で困ることはないし。

久しぶりにデスクトップPCを新しくしたら、今までのノートPC生活から劇的に性能が向上して超快適である。 やはりデスクトップPCぐらいの処理能力は欲しい。 特にカーネルやブラウザのコンパイルがこんなに早く終わるとは、Gentoo使いにとってはとても嬉しい。SEGVさえ起きなければ。(自分の環境では起きてないから今のところ問題ない)

というわけで、快適なPCが手に入ったが、今までずっとノートPCだったのでWebcamとかスピーカーも無い(イヤホンはある)ことに気付いて、色々と買い足している。 思ってたよりかなりお金がかかってしまったが、動作感やスペック的にはかなり満足のいく感じになったので、とりあえず良かった。

パーフェクトRuby第二版 こぼれ話

書籍紹介は既にいくつか書かれているんで、私は自分の担当した箇所の話を書こうかと思います。

本日(5/17)改訂2版 パーフェクトRubyが発売されます - すがブロ
改訂2版 パーフェクトRubyが出版されました - esm アジャイル事業部 開発者ブログ
改訂2版 パーフェクトRuby:書籍案内|技術評論社


私は、どっちかというと大きく書き直す所をメインで担当していました。主にテストコードの章です。後Refinementsについても少し書いてます。
テストコードの章では、書籍紹介にある様にtest-unitを採用しています。
fluentdプラグイン関連のテストコードはtest-unitで書かれていることが多いのですが、最近その辺りを結構触っているので、私が書きますよと手を挙げさせていただきました。
Refinementsについては、恐らく数少ないproduction環境でもRefinementsを活用しているものとして、貴重なユースケースを提供しておこうという意図があったので書かせてもらいましたw
私はRefinementsとても好きなんですが、実装側の苦労とか機能の限定が厳しいので、あんまり良い評判を聞かないですね……。
もちろん、そんな上手いこと使えるケースはそう多くないので、無理して使うのは止めようね、とは書いてありますw

test-unitを採用した理由ですが、この本はRubyという言語自体をテーマにした本なので、バンドルされているテスティングフレームワークを採用して書くのが入門者にとっても分かり易いだろうと思ったからです。
また、通常のRubyコードにかなり近く、特化したDSLについての事前知識を説明しなくてよかったので、内容をコンパクトに収めることができました。
ちなみに、私個人としてはRSpecは結構好きなのですが、RSpec3系になって嫌う人の気持ちも分かりますw
Power Assertも好き嫌いあると思いますが、これも言語自体にバンドルされていて、自分も関連gemを作ったりpull reqを出したりしたこともあって、ちゃんと触れています。


実際、一番しんどかったのはテストコードを書くためのサンプル実装を用意することと、モックを使ったテストを行う理屈をサンプル実装の中に用意することでした。
シンプルで読むのに苦労は無い、がテストを書くことが役に立ちそうで、リファクタリングの余地がありそうな程度に冗長なコードで、モックやスタブを紹介するためにそういうテストを書く理由が存在するコードを用意しなければならないわけです。
色々頭を捻った結果がこの本に書かれているわけですが、上手くいってるかどうかは読んでくれた人がどう受け取るか次第って所でしょうか……。
突っ込みを入れたい人は、是非、書店やgihyoさんの電子書籍サイト等でお求めください!

開発環境がLinuxに戻ってそれなりにこなれてきたので現在の環境について書く

Macを捨ててThinkpadGentooを入れて開発環境としてから2ヶ月が過ぎた。
世の中にはMacから離れようとしてThinkpadを買ったら、矢印キーボード押しにくいとかタッチパッドがクソなので、Macに戻っていった人も居るみたいですが、私としては至極快適に過ごしております。
そもそもThinkpadタッチパッドは基本無効化するものなのでどうでもいい。まあそのスペース邪魔なんだよ、とは思いますがw
Wi-Fiの無効化キーを誤爆するという危険があるらしいが、Gentooだと頑張って設定しないとそういう特殊なキーはそもそも動かないので、そんな危険もなく安全ですね。
Gentoo入れてタッチパッドを無効化すれば、Windows10というOSも使わなくていいし、全て解決するんではないでしょうか。


前置きはこのぐらいにして、色々と使うものが安定してきたので今の環境について書いていきます。

デスクトップ環境

Gentooportageというパッケージ管理システムがよく壊れるというか、依存関係が複雑なパッケージ入れてるとバージョンアップのタイミングでコンフリクトしたりする。
なので、依存関係の複雑になりがちなGUI周りのコンポーネントはできるだけ入れたくない。
というわけで、GTKベースにしつつGNOMEKDEとかいう重厚なデスクトップ環境を丸ごと入れるということはせずに、Awesomeというタイル型ウインドウマネージャーを直接起動している。
PCが起動すると、コンソールのログイン画面が出て、ログイン後にコマンドでGUIを起動するようにしている。xinitrcに"exec awesome"と書いてstartxを実行する。
おかげでめっちゃ軽い。起動直後のメモリ消費は200MB程で済む。

ランチャー

AlbertというAlfredもどきがあったのでランチャーとして使っている。
元々Alfredの高度な機能はほとんど使ってなかったので、アプリの起動さえ出来れば特に困らなかった。
Gentooにはパッケージもあったので簡単に入って便利。

ターミナル

mltermを使っている。
24bitのtrue colorが表示できて、sixelが使えるから使っているのだが、正直そこまで軽量とは感じないので、もうちょっと軽いターミナルを探している。
mltermの良い所は依存コンポーネントが少ないところ。gnome-terminalとかkonsoleとかは依存が多過ぎてもっての外だ。
urxvtが24bit表示できれば良かったのだが……。

クリップボード管理

parcelliteを使っている。
システムトレイに常駐できるし、基本的な機能があって、これも依存が少なかったので採用した。

開発環境

最近はneovimとdockerがあれば大体何とかなる。ホストOS側に色々と入れるとportageが壊れやすくなるので、できるだけdocker内に封じ込める様にしている。
コンテナ内で操作することも色々あるのでストレスなく操作できる様に、自分のzshrcとかpecoとかを突っ込んで"docker exec"を実行できる簡単なラッパースクリプトを書いている。

Twitterクライアント

TweetDeckがメイン。普通にChromiumで表示している。たまにmikutterを使うこともある。

チャット

仕事ではSlackを使っていて、Gentooにはパッケージがあったのでそれをそのまま入れて使っている。

音楽再生

wine上でfoobar2000を動かして使っている。というか未だにこれより便利な音楽プレーヤーが無いのってどうなんだ。10年前から何も変わってないぞw
自分の持ってたUSBのDAC兼ヘッドホンアンプは普通に使えたので、wine経由してWASAPIで再生している。96kもちゃんと出た。
問題は、iTunesレーティングが同期しないことで、iPhoneを使っている身としてはちょっと辛い点が増えた。

動画再生

mpvが軽くて良い。
しかし、自分のT460sは一応GeForceを積んでいるのだが、今のところLinuxでこういうノート用の追加3DコントローラーでVDPAUを上手く使う方法が無い。
色々調べたのだがかなり厳しそうだ。
DRI2で動かせば、可能性ありそうな気がするんだが、良く分からなかった。
なので、GPUは上手く活用できていない。

ファイラー

とりあえずspacefmとvimfilerを併用して使っている。
これも依存が少ないから採用した。nautilusとかGNOMEが入ってしまうので駄目だ。
その外のファイラーも大体デスクトップ環境とセットで入ってしまって辛かった。

Wi-Fi接続とbluetooth接続

それぞれコマンドでやっている。
Wi-Fiはiwコマンドかiwconfigコマンドで電源を操作して、wpa_supplicantを起動しておけば勝手に繋がった。
接続設定とかパスフレーズはwpa_passphraseコマンドの実行結果を/etc/wpa_supplicant/wpa_supplicant-.confに書いておく
bluetoothは、bluetoothctlというコマンドを使ってconnectしている。しかしBluetooth4.0規格のマウスが上手く繋がらないとか時々ハマる。
ヘッドセットとかイヤホンの類はまだ試してない。

パスワード管理

1passwordのWeb版をお試し中。wine使ってWindows版を入れるかどうかも検討しているが、まだ決めてない。

電子書籍とか画像ビューワー

KindleはwineでWindows版入れたら普通に使えた。
画像系はmcomixというビューワーでzipとかrarの中身も見れるのでこれを使っている。
PDFとかePubはあんまり良いビューワーが見つかってない。ePubFBReaderというのを使ってるが正直微妙。

マルチディスプレイ

最近は、EDIDの情報がちゃんと取れれば普通にディスプレイを認識するので、"xrandr"コマンドでディスプレイ表示を切り替えれば、大体上手く動作する。
ただ、接続チェックはちゃんとした方が良い。

まとめ

全体的な感覚としては、Macより2倍は動作が軽い。
特にタイル型ウインドウマネージャー派としては、Mac上で無理矢理やってるのとは全く反応速度が違う。久々の感覚だが、やはりこうであって欲しい。
Dockerを開発に使う上でも、変なハマりどころとかパフォーマンス上の問題が発生しないのでめっちゃ快適だった。
そもそもコンテナは起動が速いとか言ってるけど、Macだと結局VM噛んでるから別に早くないし、むしろストレージに問題ありまくりでめっちゃ辛かった。
開発機として使うなら、やはりLinuxの方が良い。iOS開発者はどうしようもないけど……。
最近のLinuxは蓋を閉めたらちゃんとスリープできるので、バッテリー問題も困ることはそんなに無い。
まあ、稀に復帰できないことはあるんだけど、そもそもMacでも時々復帰しないし。
CPUがあんまり高クロックで動作しない様に上限かければ6時間は電池が持つ。


というわけで、今のMacが気に入らないなら、そろそろMacから離れる好機かもしれない。
宗教上の理由でLenovoのPCを使いたくない、という人も居るかもしれないし、別にThinkpadを進めるわけではないけど……。


2/3 15:00 追記
はてブコメントで、資料作成とOfficeどうしてるんだろう?というものがチラホラあったので追記しました。

資料作成について

資料は、よっぽどビジュアルに凝ったものを作る場合を除いてmarkdownで書いてreveal.jsで表示する形にしている。
Mac使ってた時も最近の時期はそうだった。
ビジュアルが必要なかっちりした発表の時は、仕方ないのでMacを引っ張り出してきてkeynote使うかもしれない。

Officeについて

一応、必要になったらlibreofficeを入れようと思っているが、ここ3年でプレゼンテーション資料以外の用途でOfficeっぽいものが必要になったことはない。
基本的にはGoogle DocsGoogle Spreadsheetで対処している。
そもそもMacにもOffice自体は入ってなかった。あのKeyNoteの付属品みたいなものは、あんま役に立たないし……。
謎マクロが大量に入ったExcelがやってきたら詰むけど、元々の状況に変化は無いw