console.blog(self);

技術、読んだ本、いろいろ。

35歳になった

人生の折り返し、後半が始まった。

中学生くらいのときに「回転木馬のデッド・ヒート」という短編集の「プールサイド」という作品を読んでから、35歳が人生の折り返しだと思って生きてきた。

「プールサイド」はこんな書き出しで始まる。

35歳になった春、彼は自分が既に人生の折り返し点を曲がってしまったことを確認した。

いや、これは正確な表現ではない。正確に言うなら、35歳の春にして彼は人生の折りかえし点を曲がろうと決心した、ということになるだろう。

回転木馬のデッド・ヒート

この「彼」が35歳になったのは1983年3月26日のことで、いまでは68歳のはず。どんな人生になっているんだろう。

後半が始まるということは前半が終わったということで、35年間、いろいろあったなあと思ったりする。相変わらず長期展望はなく、瞬間の積み重ねで35年が過ぎたんだと感じる。「泳ぐのに、安全でも適切でもありません」のあとがきを思い出す。

瞬間の集積が時間であり、時間の集積が人生であるならば、私はやっぱり瞬間を信じたい。SAFE でも SUITABLE でもない人生で、長期展望にどのような意味があるのでしょうか。

泳ぐのに、安全でも適切でもありません

十代はばたばたしていて、そのおかげで諦観のようなものをちょっとだけ身につけた気がする。たいていのことはなんとかなるし、どうにものならないこともある、みたいな。

二十代はSIerでいろいろ案件をやっていた。いまになって、このころの経験が活かせるようになってきた気がする。

三十代はいいこともわるいこともたくさんあった。アップダウンが激しかったけど、いいことのほうが多かった。

ちょくちょくふりかえっていて、というかふりかえりしか書いていなくて、もうちょっとアウトプットしなければと年初に誓ったのだが全然できていない。もうちょっと頑張らないと。


最近、これからの働き方がちょっと見えてきた。「組織をエンジニアリングする」という感じ。もうちょっと推敲が必要だけど。

DevOptsや、Infrastructure as Codeにちょっと近いイメージ。Infrastructure as Codeでは、ソフトウェア開発のプラクティスをインフラの構成管理などで利用している。

これまでエンジニアとして身につけた技術をベースに、組織、戦略、マネジメントなどに取り組んでいきたい。新しいプラットフォームと言語でプログラミングするように、組織に取り組みマネジメントする。そんな感じでやっていると、マネジメントしている感じがしなくなってきた。

例えば、毎日新しい問題が起きたりするけど、毎日障害が起きるシステムの安定化に取り組んでいるようなものに思える。問題を切り分けて、仮説、検証を行っていく。

これをもうちょっとパターン化したり、プラクティスのようにまとめていきたい。


「デザインと技術をつなぐ」ということを、これから数年掛けてやっていく。言語化したことで明確になり、これから取り組むことを徐々にイメージできるようになってきた。

エンジニアとしてのバックグラウンドを、デザインや組織といったエンジニアリング以外のところで活かしたい。うまくできるかわからないけど、やりきりたい。


34歳はけっこうたのしかった。この1年もたのしくなるといいな。

2015年の振り返りと、2016年の初心

あけましておめでとうございます。今年もよろしくお願いいたします。

去年はこんなことを書いていた。

2015年の振り返り

Goodpatchに入社して、1年が経った。

CTOになった

もともとSIerに9年勤めて、マネージメント系の仕事が多くなってきて、もっとコード書きたいなーと思って転職した。2社目で大規模なサービス開発をあれこれやって、がりごりRubyJavaScript書いた。2年くらいたったら、やっぱりマネージメント系の業務を求められることが多くなってきた。

もっとコード書きたいと思って、Goodpatchに転職した。入社してみるとチームによいエンジニアが揃っているけどマネジメントする人がいなくて、もったいないなと思ってマネジメントをするようになった。そのほうがProttというプロダクトを成長させることができると思った。

Goodpatchではコードを書いた時間より、マネジメントをしていた時間が圧倒的に多かった。そういう働き方を自分で選んだ。

その後もいいエンジニアがどんどん入ってきてくれて、自分ならこんな風に作りたいなって思ったことをチームメンバーがどんどん実現してくれた。エンジニアとしての社会人経験が12年になるけど、はじめてコードを書くよりマネージメントしたほうが貢献できると感じた。

1月に入社して、3月ごろにプロダクトのエンジニアリーダーになって、12月に執行役員CTOになった。役員になることが前提で入社したわけではなく、エンジニアリーダーとして働いているなかで声を掛けてもらった。

いろいろな解釈があるけど、僕にとって執行役員というのは社員ではなく経営者だ。「JavaからRubyへ」という選択をして、その3年半後に「エンジニアから経営者へ」になった。

最初に転職するときに「はたらきたい。」を読んで「大切にしているものは、何ですか?」ということを考えた。CTOというキャリアを選択をするときも、同じことを考えた。

キーワードは「大切にしているものは、何ですか?」

新装版 ほぼ日の就職論「はたらきたい。」

僕にとっては「変化に対応していきたい」だった。ありきたりな感じだけど、考え抜いてでてきたことだった。そしてこれが僕の行動規範になっている。

ノルウェイの森」で永沢さんは行動規範についてこんなことを言っている。

人生にはそんなもの必要ないんだ。必要なものは理想ではなく行動規範だ

ノルウェイの森

永沢さんの行動規範は「紳士であることだ」と答え、紳士の定義として「自分がやりたいことをやるのではなく、やるべきことをやるのが紳士だ」と答えている。

大切にしているものや行動規範が明確になっていると、迷いにくくなる。新しいことをやるとき、こんなことが浮かんだりする。

  • 楽しいか?
  • 大変か?
  • 成長できるか?
  • 成果を出せるか?

でも自分にとって大切なことは「変化に対応していきたい」なので「変化が大きいか?」を基準に考える。この1年は、とにかく変化の大きい方を選んできた。

Goodpatchは「ハートを揺さぶるデザインで世界を前進させる」ということをビジョンに掲げている。それに共感していて、大変なことはたくさんあるけど、この先になにか楽しいことがありそうだから頑張る。

デザインと経営とエンジニアリングを繋げて、よいチーム、よいプロダクト、よい会社を作っていく。

英語

あんまり書いてこなかったけど、いちばん大きな変化は英語を使うようになったことだと思う。学生時代は一貫して英語を無視していた。使うことがなかったから。

エンジニアになって、仕様書や英語の文献はある程度読んできたけど、日常的に英語を使うことはなかった。読むことはあっても、書くこと、聞くこと、話すことはなかった。

ちょこちょこ勉強して、ものすごく苦手な状態から、なんとかコミュニケーションをとることができる、くらいの状態になった。2015年は仕事でベルリンに3週間行ったり、個人的にシリコンバレーに1週間行ったりした。

簡単な議論できるくらいまで上達したい。また勉強する。

2016年の初心

2016年に注力することを考えて、あれこれ浮かんだけど絞ってみるとこんな感じになった。

本を読んで、必ずblogに書く。

とてもシンプルになった。

Why

これまでとは違った業務に携わることになった。知識が足りないので、早急に補う必要がある。

分野だけ上げるとこんな感じ。

  • デザイン
  • プロダクト
  • 経営
  • 組織

これらの分野とエンジニアリングを組み合わせて成果を上げていくことが自分の責任だと思っている。エンジニアリングの力で、デザインと経営と組織を支えていきたい。

How

inputとoutputを増やす。知識を得て、それを使うことで経験にしていく。

What

本を読んで、必ずblogに書く。これがいちばんよい方法なのかはわからないけど、勉強したことをblogに書くことで成長してきたので、まずはこれまでに成果のでている方法を試してみる。この方法が行き詰まるくらい本を読んだら、また違ったものが見えてくるだろうし。

まとめ

今年がよい1年になるといいな、していきたいな、と思っていたら、「神様のレシピ」を思い出した。

「神様のレシピだ」日比野が表情を変えずに言った。「未来は神様のレシピで決まる

錯覚ではあったが、カカシはうなずいたかのように見えた。「神様のレシピにはとても多くの材料が並んでいて、贅沢です」

僕はそれをとてもいい響きの言葉だ、と思った

オーデュボンの祈り

エンジニアリングと、デザインと経営と組織を繋げるって、わくわくする。もちろん難しくて大変だろうけど。デザインの力をエンジニアリングで支える組織を作って、経営がそれを持続させる。とても多くの材料が並んでいて、贅沢だ。

個人的に35歳を人生の折り返し地点だと思っていて、そこまであと半年を切った。これからも変化に対応していきたい。

1年間で取り組んだProttのパフォーマンスチューニング

f:id:sadah:20151225074123p:plain

Goodpatch CTOの id:sadah です。

これはGoodpatch Advent Calendar 2015の25日目のエントリです。

Prottというサービスではパフォーマンスチューニングのために、Railsアプリケーション/フロントエンドの改善、ミドルウェアのバージョンアップ、SPDYやHTTP/2の導入、オンプレミス環境からAWSへの移行などを行ってきました。 今回はその取り組みの一部をご紹介します。

Slides

10月にGoodpatch Engineer Meetupというイベントをやって、Prottのパフォーマンスチューニングについて話した。

イベントの内容はこちらにまとまっている。

僕のスライドはこんな感じ。

"Make the Prott Faster"ってタイトルにしたけど、theはいらないよってあとから教えてもらった。cute misstakeって言われた。感覚がわからない。

パフォーマンスチューニングで取り組んだこと

Goodpatchには2015年1月に入社して、そこからいろいろなことに取り組んできた。10月の時点で2倍くらいは速くなった。いまはさらに速くなっている。でもまだまだ改善できるので、来年もパフォーマンスチューニングに取り組んでいく。 2015年10月に計測したときはこんな感じだった。

f:id:sadah:20151225074418j:plain

f:id:sadah:20151225074437j:plain

イベントのあった10月までに、こんなことをやってきた。

  • Infrastructure
    • RubyRailsのバージョンアップ
    • Nginxのチューニング
    • SPDYの導入(HAProxyからNginxへの移行)
  • Rails Application
    • N+1問題の解消(道半ば)
    • Slow Queryの解消
    • メモ化
    • Cache(Russian Doll Caching)
  • Frontend
    • AngularJSバージョンアップ
    • $watchの削減

11月から12月にかけて大きな変更をした。

  • Infrastructure
    • オンプレミス環境からAWSへの移行(計画停止しての移行)
    • MongoDB / Nginx など各種ミドルウェアのバージョンアップ
    • HTTP/2の導入

僕は主にRails側の対応を行い、フロントエンドやインフラの対応はチームメンバーがやってくれた。SPDY導入や、$watchの削減についてはこちらの資料にまとまっている。

Prottの抱えていた課題

プロジェクト一覧の画面が遅い。

f:id:sadah:20151225074858j:plain

スクリーン一覧の画面が遅い。

f:id:sadah:20151225074920j:plain

このよく使うページを中心に改善していった。

パフォーマンスチューニングの指針

よく言われていることを、ちゃんと実践するようにする。

f:id:sadah:20151225074958j:plain

  • 推測するな、計測せよ。
  • 時期尚早な最適化は諸悪の根源だ。
  • 1度に修正するのは1箇所のみ。

このあたりに詳しく書いてある。

ただこのときは、時期尚早どころか
もっと早く対応するべきだった…。

SPDY

f:id:sadah:20151225075102j:plain

SPDYの導入にあたってはこんなことをした(いまはHTTP/2を使っているけど)。

  • spdycatで接続確認する
  • h2loadで計測する

このあたりを参考にさせていただいた。

spdycatを使うと、こんなふうに接続確認ができる。

% spdycat https://prottapp.com/ -v -n
[  0.379] NPN select next protocol: the remote server offers:
          * spdy/3.1
          * http/1.1
          NPN selected the protocol: spdy/3.1
[  0.386] Handshake complete
[  0.387] recv SETTINGS frame <version=3, flags=1, length=20>
          (niv=2)
          [4(0):100]
          [7(0):2147483647]
[  0.387] recv WINDOW_UPDATE frame <version=3, flags=0, length=8>
          (stream_id=0, delta_window_size=2147418111)
[  0.387] send SYN_STREAM frame <version=3, flags=1, length=215>
          (stream_id=1, assoc_stream_id=0, pri=3)
          :host: prottapp.com
          :method: GET
          :path: /
          :scheme: https
          :version: HTTP/1.1
          accept: */*
          accept-encoding: gzip, deflate
          user-agent: spdylay/1.3.2

h2loadで負荷を掛けられる。cでクライアント数、nで回数を指定できる。出力はこんな感じ。

% h2load -c 1 -n 1 https://prottapp.com
starting benchmark...
spawning thread #0: 1 concurrent clients, 1 total requests
Protocol: TLSv1.2
Cipher: ECDHE-RSA-AES256-GCM-SHA384
Server Temp Key: ECDH P-256 256 bits
progress: 100% done

finished in 117.42ms, 8.51665 req/s, 1.29MB/s
requests: 1 total, 1 started, 1 done, 1 succeeded, 0 failed, 0 errored, 0 timeout
status codes: 1 2xx, 0 3xx, 0 4xx, 0 5xx
traffic: 158829 bytes total, 375 bytes headers, 158106 bytes data
                     min         max         mean         sd        +/- sd
time for request:    78.29ms     78.29ms     78.29ms         0us   100.00%
time for connect:    38.74ms     38.74ms     38.74ms         0us   100.00%
time to 1st byte:    90.82ms     90.82ms     90.82ms         0us   100.00%

開発環境でApache Benchとh2loadで測定したら、レスポンスタイムが10%程度改善した。あんまり厳密は計測していなくて、遅くなったりしないことだけ確認した。

MongoDBのSlowQuery

mongoidのexplainメソッドだとほしい情報が取れなかった(executionStatsを渡した結果がほしかった)ので、monogo shellでexplainした。

> db.xxxx.find({ deleted_at: null, screen_id: ObjectId('XXXXXXXXXXXX')}).sort({_id:1}).explain('executionStats')

{ "queryPlanner" : { ...
  "winningPlan" : {
          "stage" : "FETCH", ...
  },},
"executionStats" : { ...
  "executionTimeMillis" : 111,
  "totalKeysExamined" : 55555,
  "totalDocsExamined" : 55555,
} }

winningPlanの内容を確認すると、stageがFETCHになってはいるけど、sortが効いてるだけっぽい。 検索したindexの数と検索したdocumentの数が同一になってしまっているので、indexは効いていなかった。

indexを追加することで改善した。

> db.xxxx.find({ deleted_at: null, screen_id: ObjectId('XXXXXXXXXXXX')}).sort({_id:1}).explain('executionStats')

{ "queryPlanner" : { ...
  "winningPlan" : {
          "stage" : "FETCH", ...
  },},
"executionStats" : { ...
  "executionTimeMillis" : 2,
  "totalKeysExamined" : 1,
  "totalDocsExamined" : 1,
} }

Rails Application

計測するためにつかったツールとか。

使わなかったツールとか。

stackprofとstackprof-webnav

stackprof

stackprofはRubyのプロファイラ。作者はGitHubのAman Gupta(@tmm1)さん。RubyKaigi2014 3日目の基調講演のスピーカーでセッション終了後の拍手がものすごかった。

RubyKaigi2014でのスライドはこちら。

config.ruをこんな感じにするとRAILS_ROOT/tmpにダンプができる。

require ::File.expand_path('../config/environment',  __FILE__)

use StackProf::Middleware, enabled:    true,
                           mode:       :cpu,
                           raw:        true,
                           interval:   1000,
                           save_every: 5
run Rails.application

stackprofで解析するとこんな感じ。

$ stackprof tmp/stackprof-cpu-*.dump --text --limit 1
==================================
  Mode: cpu(1000)
  Samples: 780 (5.45% miss rate)
  GC: 88 (11.28%)
==================================
     TOTAL    (pct)     SAMPLES    (pct)     FRAME
        33   (4.2%)          27   (3.5%)     Psych::ScalarScanner#tokenize

stackprof-webnav

stackprofの出力をWebで確認できる。ドリルダウンとかできて便利。

$ gem install stackprof-webnav
$ stackprof-webnav -f tmp/stackprof-cpu-53222-1444801808.dump

こんな感じで表示される。

f:id:sadah:20151225075311j:plain

こんな感じでドリルダウンできる。

f:id:sadah:20151225075355j:plain

Frontend

画像の Layout / Paint が重かった。Chrome DevTools の timeline を使って計測。画像を縮小して表示している部分が重かった。

f:id:sadah:20151225075536j:plain

DevToolsのUI、カオス。そしてまたいろいろ変わっているんだろうな。Renderingタブにいろいろ設定がある。

f:id:sadah:20151225075606j:plain

いろいろ有効にすると、LayerやFPSを確認できる。

f:id:sadah:20151225075634j:plain

改善するために、試しにtransform使ってGPU使ってみた(ちょっと試してみたかった)。速くなったけど根本的な解決じゃないではないので、Nginx(ngx_small_light)で縮小したサイズの画像を生成することにした。

画像への初回リクエスト時に指定されたサイズの画像を生成しキャッシュするようにした。適切なサイズの画像を使うことで、ブラウザがかなりスムーズに動くようになった。

あとはこんなツールを使ったり、細かいJSの改善をやり続けていった。

AWS

これらの取り組みのあと、インフラをオンプレミス環境からAWSに移行した。地理的には東京からオレゴンに移行した。Prottをグローバルに使われるサービスにしていくために必要なことだった。とても難しい決断だった。

ヨーロッパでProttが遅いという報告を以前から受けていて、10月から11月にかけてベルリンに行って調査した。アメリカにサーバを置くと、かなり改善することがわかった。もちろん日本からのアクセスのレイテンシーは大きくなる。

そのため、AWS化にともないNginx / MongoDBなど主要なミドルウェアのバージョンアップを行い、さらに使うインスタンスのスペックを上げた。

その結果、日本からのアクセスのレイテンシーは増えたけどパフォーマンスは上がり、これまでよりも速くなった。ヨーロッパやアメリカでは格段に速くなった。

事前にしっかり準備することで、大きな問題も起こさずに移行を完了できた。海外のメンバーから、Prottが速くなった!というメッセージをたくさんもらえて、とてもうれしかった。

まとめ

フロントエンドの改善は id:yoshiko_pg が、がつがつ進めてくれた。インフラ周りのほとんどの作業を id:urapico が担当してくれた。他のメンバーもいろいろな改善をやってくれた。

経営的判断として、パフォーマンスチューニングを最優先課題として取り組んだ。チーム全体でパフォーマンスチューニングに
取り組む期間を作れたことはとてもよかった。

ただ、まだまだボトルネックになっているところは多いし、もっと速くしていかなくてはならない。例えばキャッシュで速くなっても初回アクセスの重さが解消できていないし、当たり前の設定を入れた感じなので
もっと攻めたい。

Goodpatchは「ハートを揺さぶるデザインで世界を前進させる」というビジョンを掲げている。サービスが遅いと
ハートを揺さぶれない。パフォーマンスは
UXに直結する。

Prottをもっとよいサービスにするために、来年もいろいろなことに取り組んでいく。

We are hiring!!

Prottを改善していくエンジニアを募集しています!興味があれば気軽に連絡ください。