「予定あり」「予定なし」という概念があり、これが「予定あり」の予定が入っているときのみ「時間を探す」などでブロックされる。 言い換えると予定が「予定なし」だと他の人からは空いているように見える。
ちなみに「終日」にするとデフォルトが「予定なし」になる挙動 (現時点) のようなので留意しましょう。
「予定なし」の予定
「予定あり」の予定
いかがでしたか?
「予定なし」の予定とかむずかしい日本語ですね。
- Fix mirror() (haarg) #9
https://metacpan.org/changes/release/MIYAGAWA/LWP-Protocol-PSGI-0.10#L4
changesには `LWP::UserAgent#mirror` についてのみ言及があるけど、`get()` メソッドの `:content_file` 引数にも影響がある。
`mirror` メソッドも `:content_file` 引数も紆余曲折あり `LWP::Protocol#collect` を呼ぶことでレスポンスボディがファイルに保存される。
fix LWP::UA::mirror calls by haarg · Pull Request #9 · miyagawa/LWP-Protocol-PSGI
上記Pull Requestはつまるところ適切に `collect` を呼ぶようにする変更なので、 `mirror` も `:content_file` も適切に処理される、ということだった。
昨年末からぼちぼち書いている。
……を目的に考えて日記を書くためのブログシステムを書きはじめた。
Web技術で遊び続ける定まった場所がないと、技術を使うための技術の域を出ない学習が続くなという問題意識から何か作ることにし、自分はWebでテキストを書くのが大好き人間なので、ブログシステムを作ることにした。
それでも自作するか
ブログシステムは自作すべきか? ブログサービス VS 自作システム | tech - 氾濫原
もしウェブプログラマなら自作すべきであると常に主張したい。
自分もこの意見に賛成で、まあブログシステムであることにこだわらなくてもいいけれど、趣味なら車輪の再発明など恐れずにとにかく遊び続けるのがいいと思う。
また完全無欠のASP型のサービスなどありえないわけで、その点では自作するとき自分が求めていてASPサービスにないものを作れるならば、それは完全な車輪の再発明とはいえないし、得るものは大きいと思う。
パフォーマンスチューニングを目的に挙げているのは、仕事でもWebアプリケーションを作っているがそもそもパフォーマンスについて考える時間が少ないので知識も技術も身に付かない、けど求められるものではあるというギャップを埋めるためでもある。
そしてこうした興味・好奇心だけを目的とせず、使う自分自身の満足度・快適さに対する解決の手段として自分の興味がある技術を選べるような題材という点でも、ブログシステムは適している。
ソフトウェアエンジニア一般が趣味の開発でこうしたモチベーションでいるべきと考えているわけではなく、単に自分が趣味で作ることを考えるとき自分がよく使うもので、かつうまく動いていると自分が一番に喜ぶものでないと、継続して触りつづけるモチベーションが保たないだろうということを見越した、合理的な理由による。
インフラはGoogle Cloud Platform、configuration managementを考えるのがだるいのでランタイムはコンテナに任せようということでk8s (GKE) を選んだ。
仕事でAWSを使っているので、では趣味ならGCPというくらい。あと料金計算が明快なのがいい、AWSはリザーブドインスタンスとか考えはじめると勘定がめんどう。
いまVPSに月におよそ1000円くらい払っているので、これを解約することを見越してプラス勉強代として月2000円まででやりくりしようと思っている。
パフォーマンスチューニングを深追いしたいということで、ポピュラーになったCDNは採用せず自分でリバースプロキシを運用することにした。
サーバサイドはRuby, DBはPostgreSQL, 記事の編集画面はTypeScriptで書いている。
インフラとフロントエンドが弱いと感じていて、そちらにリソースを割きたいのでサーバサイドは使い慣れたRubyにした。
Rubyはぱっと作ることができて安定感があるものの、型がなかったりもうちょっと冒険してもいいかなと思っている。
とはいえパッケージ管理とかでむやみにハマっていたくないし、予算上、ホストのメモリとかは潤沢にはできないのでScalaは選びづらいし、仕事でも趣味でもGoをよく書いており食傷気味なので、やはり落とし所として妥当かと思っている。
本当はサーバサイドはホットスポットではないのでGAEにしてもよかったんだけれども、予算の都合でStandard Environmentしか使えず、StandardだとJavaかPythonかGoかPHPで、どれも気乗りしなかったのでGKEにした。
フロントエンドはそのうちSPAにしてみたい。
昔、仕事でSPAを触っていたけどhistory APIにバグのある地獄みたいな環境向けだったので、今のまともなブラウザと充実してきたと思われるライブラリ類で、リソース管理などの煩雑さが減ったのかそうでもないのか確かめてみたい。
いまは最低限、記事を書いてそれを配信するところまではできたのでGKEにデプロイしようとしている。
Kubernetesは耳慣れない概念がたくさん出てくるので難しいけど、GCPのドキュメントが充実しているのでチュートリアルを見様見真似でやりつつ要件・予算にあわせてあれこれ手探りで変えて試している。
sudo mkdir -p /opt/mackerel-agent/plugins sudo chown -R $(id -un):$(id -gn) /opt/mackerel-agent/plugins mkr plugin install aereal/mackerel-plugin-macbook-battery-health@v0.0.2 cat <<EOS >> /usr/local/etc/mackerel-agent.conf [plugin.metrics.macbook_battery_health] command = "/opt/mackerel-agent/plugins/bin/mackerel-plugin-macbook-battery-health" EOS
以前作ったプラグインを `mkr plugin install`-readyにした。
対応といっても命名規則を整えてGitHubにリリースしたくらいで非常に手軽で便利。手順はMackerel公式のドキュメントが詳しくてわかりやすい。
実際に対応するための変更は以下のPull Requestにまとまっている。ちゃんと読んでいなくてzipじゃないとダメとか命名規則とかが適合していなくて無駄にトライアンドエラーを繰り返してしまった。
バッテリ残量の監視はなにかと便利なのでどうぞご利用ください。
r7さんらの振り返りがおもしろかったので自分も書き出した。
5,184 JPY/year
過去作から最新作までたくさん配信されているのでなにか見たいな〜という時に便利。
最近はテレビ放映とタイミングを揃えて配信される作品が増えたのでほんとうに良い時代になった。
今は京都という割と地上波のチャンネルに恵まれた地域に住んでいるけれど、地元は北海道なので深夜アニメがまったく見れずに悲しい思いをしてきたので、地域差が縮まるのは歓迎。
配信の仕組み自体は素朴という印象で、AmazonプライムビデオやNetflixと違いビットレートを調節してバッファリングの時間を減らすとかそういう取り組みはしてなさそうなので、ネットワークの品質に問題があるとストレスを感じることもある。
3,900 JPY/year
お急ぎ便などなどに使っている。あとプライムビデオのラインナップが絶妙で、dアニメストアと補完しあったり昔見たおぼえのある映画をたまに見ている。
9,492 JPY/year
いつのまにかDeveloper planだとprivateリポジトリの上限がなくなってますます便利になった。
スケッチとかIntelliJの設定 (自動でコミットされるのでまずい内容が出てしまわないか心配なのでprivateにしている) などとりあえずprivateでも作っておけるという安心感を買っているようなもの。
26,640 JPY/year (6GB ライトスタートプラン)
数年前にauからMNPしてずっと使っている。京都で生活していると人が多くて遅いというようなこともなく快適。
もともと3GBのプランだったけれど旅行で外に出る日が続くとすぐにクーポンを使い切ってしまうので6GBにした。
44,352 JPY/year → ?
一人暮らししてから家の回線はWiMAXを契約しておりその流れで今も使っている。
……が、いまは通信量に上限があり、それはよいとしても課金して制限を解除する道も提供されていないので潮時かなーと思いしばらく立つ。
固定回線は、それはそれで地域において品質の良いISPを見つけること、工事に立ちあう必要があること、などから二の足を踏んでおりいまだにどうしようか考えるがまあいいかな……と思う。
次に引っ越すことがあったら諦めて固定回線を契約すると思う。
11,760 JPY/year
Lightroomなど使うために入っている。
11,760 JPY/year
ポピュラー音楽のラインナップは特に琴線に触れるところはないけどクラシックのラインナップが満足できる。
聞きたいオーケストラの盤が揃っているので好きな時に聞き比べたり参考にできるので気に入っている。
1,080 JPY/year
旅行で東海道・山陽新幹線やJR西日本の特急に乗る機会が増えたので契約した。
会社で出張するときは会社が契約しているEX-ICで新幹線に乗るのだけれど、あれを知ったら直前まで予約が変更できる便利さなしでは生きていけない。
のぞみに1回乗った時の割引額が1,080円なので1年に2回乗ったら回収できるのでかなりお得だと思う。
あと海外旅行前にVISAではなくMASTERCARDのカードを手に入れる目的もあった。
(解約) → 11,400 JPY/year
「ヴァイオレット・エヴァーガーデン」「からかい上手の高木さん」の配信がNetflixだけだったので再度契約した。
バッファリングの短さとか視聴するときのストレスのなさは使ったことのあるサービスの中では一番だと思う。
21,384 JPY/year → 10,692 JPY/year
1GBプランを2つ契約していたけど1つにした。
Elasticsearchとか計算機リソースを使うミドルウェアで遊ぶ時は、リソース単価の安いVPSのほうが使い出がある。
16,800 JPY/year → 1,047 JPY/year (予定)
古い写真のRAW画像の保存にGlacierを、このブログなどなどのドメインのネームサーバとしてRoute 53を使っており、これで年1,047円くらい。
……のつもりだったのだけれども、昨年明けに検証のために立てたEC2インスタンスを落とし忘れていて昨年1年間ずっと毎月10USDかかっていたことがわかって慌てて解約した。
6,000 JPY/year → 解約
家計レポートとか見れたらおもしろいかなと思って契約したけど既に述べたようにEC2のインスタンスを起動しっぱなしで気付かないような人間なので、まずMoneyForwardにお金を払う前にやるべきことがたくさんあることに気がつき解約した。
EC2インスタンスを起動しっぱなしにする人間は何をやってもダメ。
年 | 金額 | 前年比 |
---|---|---|
2017 | 483,040円 | 124.09% |
2016 | 389,277円 | 124.54% |
2015 | 312,547円 | 136.27% |
2014 | 229,352円 | - |
カメラやレンズなどは含んでいない。主に Kindle 本や生活用品など。
この調子でいくと来年は45万くらい年間で使う目測だけど、そんなに成長するかな、どうかな。
数字で振り返った2016年 - Sexually Knowing
順調に124%成長が続いている、すごい。後で紹介するように給与は毎年110%ペースくらいなので、いつか追い付かれる。
入社して以来、給与明細をGoogle Driveに保存してあり、支給額 (手取り) を12掛けして年俸額とした。
なので年俸額なのにやけにピコピコしている。
営業期が変わるタイミング (1月と7月) に人事評価がありそこで報酬が変わるので、だいたいそのタイミングで大きく変わる。
グレードという給与レンジを定めた概念が全6段階あって、それが変わるとベースも変わるのでそこで大きく変わる要因はそれくらいと見える。
いちおうグレードは役職と関係ないということになっている。
ちなみに控除額も有史以来記録してあり、見るとげんなりするもののひとつ。
年 | 記事数 | 前年比 |
---|---|---|
2017 | 53 | 72.60% |
2016 | 73 | 486.7% |
2015 | 15 | 13.0% |
2014 | 115 | - |
一転、減ってしまった。1月に大雪があったりクロアチア旅行に行ったり前半はよく撮ったし、後半も撮っていないこともないけれど上げていく気力がなかった。
9月から今もずっと仕事で完全に頭が参ってしまっている。書いていたらなんで仕事に忙殺されてこんな虚しい振り返りをしているんだとイラついてきた。
年 | 記事数 | 前年比 |
---|---|---|
2017 | 87 | 55.76% |
2016 | 156 | 91.22% |
2015 | 171 | 54.11% |
2014 | 316 | - |
ほぼ半減した。9月くらいから本当に気が参って「仕事やめたい」とか「1000万ほしい」としか書いてない下書きがたくさんある。
近しい人に読んでほしくないので接続元のIPが地理的に近かったら見れなくするとか、そういうことをしたいな。
その昔Powを使っていた名残で、開発時のループバックドメインに `.dev` をよく使っていたのだけれど、最近うまく動かなくて調べたところ、HTTPSで通信しようとして失敗していた。
アプリケーションでそんな設定した覚えないんだけどな……と訝しんでいたら、どうやらChrome (Chromium) に変更があり先読みするドメインのリストでHTTPSを強制する設定が追加されたらしい。
Chrome 63 forces .dev domains to HTTPS via preloaded HSTS
`.dev` はGoogleによって買われたらしいという話も書いてあって初耳。
それはそうとどうすればいいかというと、テスト・開発用に予約されたTLDがあるのでそれを使うのがよいだろうと上記記事には書いてある。
`.test` や新たに追加された `.localhost` などがそれにあたるので、それを使うのがよかろう、と。
元々予約されているわけでもなんでもなかったのでいきなり壊れても文句は言えないけど、しかしこういう変更入れることもあるんだなーという発見があった。
結論: 値がcomma-separated listと定められているヘッダはOK
こういう出力:
... Vary: Accept-Encoding Vary: User-Agent ...
RFCより引用:
A sender MUST NOT generate multiple header fields with the same field name in a message unless either the entire field value for that header field is defined as a comma-separated list [i.e., #(values)] or the header field is a well-known exception (as noted below).
RFC 7230 - Hypertext Transfer Protocol (HTTP/1.1): Message Syntax and Routing
A recipient MAY combine multiple header fields with the same field name into one "field-name: field-value" pair, without changing the semantics of the message, by appending each subsequent field value to the combined field value in order, separated by a comma.
RFC 7230 - Hypertext Transfer Protocol (HTTP/1.1): Message Syntax and Routing
ということが書いてあります。
つまり以下のヘッダ出力があったとき:
... Vary: Accept-Encoding Vary: User-Agent ...
……受信者は以下のように結合するかもしれません:
... Vary: Accept-Encoding, User-Agent ...
いいやつを作った。
AWS SDK for Goを使っているのでIAM roleが適切に設定されたEC2のインスタンス上ならAWSの認証情報は特別渡さなくてよい
(もちろん環境変数で渡してもよい) ので、MackerelのAPI keyとサービス名さえ渡せばすぐに使えます。
さらに `-no-post` でSensu互換形式でstdoutに出力だけすることもできるので、mackerel-agentが動いているホストでmkrがインストールされていればサービス名だけ渡すだけで動くので便利。
mackerel-aws-s3-stats --region ... --bucket ... --no-post | mkr throw --service my-service
GitHub - aereal/gae-go-netatmo-ws-mackerel
冬なのでNetatmo Weather Stationを購入して自宅で動かしはじめました。エアコンをつけるといきなり室温が上がってエアコンはすごいなーということがよくわかって便利。
ウェザーステーション Netatmo Weather Station 【並行輸入品】
ハードウェアももちろんWebサービスとアプリもよくできていて、単に現在のデータを見るだけならこれで十分ですが、不快指数を計算したらなにかとアラートを送ったりしたいのでMackerelに投げたい。
ので書きました。GAE/Goで動くやつです。
元々、同僚がGoogle Apps ScriptとAWS Lambdaで動かす実装を作っていてだいたいそれを参考にした。
家で動かすものでメンテフリーにしたく、GASは1週間後読み書きできる気はしないしAWS Lambdaはいいけどもっと素朴なWebアプリケーションで開発したいなと思ったのでGAE/Goで動かしています。
詳しくはREADMEに書いてあるけど、普通のWebアプリケーションとして動かし、GAEのcron機能で定期的にリクエストさせることで定期的にメトリックを送ることができる。
ポイントとしては:
感想:
実行環境をコンテナ化するDockerが普及して久しく、CIやローカルの開発環境などどこかでコンテナ技術に触れているのではないでしょうか。
コンテナはその性質上、設定のプロビジョニングに古典的な設定ファイル (のパス) 受け渡しが難しいです。etcdやconsulのようなKVS (= Key-value store) を用いることもあるでしょうが、素朴には環境変数で与えることが多いでしょう。
HerokuはThe Twelve-Factor Appというパターンを提唱し、その中でStore config in the environment
と述べています。
The twelve-factor app stores config in environment variables (often shortened to env vars or env). Env vars are easy to change between deploys without changing any code; unlike config files, there is little chance of them being checked into the code repo accidentally; and unlike custom config files, or other config mechanisms such as Java System Properties, they are a language- and OS-agnostic standard.
The Twelve-Factor App
参考: Building Twelve Factor Apps on Heroku | Heroku
しかし環境変数はグローバル変数なので無闇に参照すれば古式ゆかしきスパゲティコードまっしぐらです。また環境変数の値は文字列として扱われるので表現力に乏しく利用者のために値の定義域を示す必要がしばしば生じますが、どのように行うべきでしょうか?
そんな悩みをJSON Schemaで解決しようという試みを紹介します。
ある環境変数がとりうる値の形式や範囲を考えてみます。
たとえば真偽値 (boolean) が挙げられます。 DEBUG=1
でデバッグフラグを立てるような変数です。
1か0か、あるいは値はなんでもよくて定義されていれば真とする場合もありますが、併せて真偽値とします。
あるいは数値 (number) も考えられます。 LOGLEVEL=1
や LOGLEVEL=7
など、ログ出力を数値で指定するケースがあります。
真偽値と数値を一般化すると列挙 (enum, enumeration) になります。たとえば PLACK_ENV=test
PLACK_ENV=production
など、文字列として扱われるがそのとりうる値があらかじめいくつかに決まっています。
また特殊な例として複数値 (multiple values) についても考える必要があります。
環境変数は辞書構造なので、ある名前に対応する値はただひとつに定められるため、複数の値を渡したい場合は値をデータ区切り文字 (delimiter) で分割して扱います。
たとえば PATH
は値をコロンで区切ります *1。
PATH
はコロンで区切るというコンセンサスが得られているのであまり問題になりませんが、独自の変数を定義するときに区切り文字は何であるかはいよいよもって明示しなければ正しく使うことはできません。
そこでJSON Schemaを利用します。
JSON Schema (JSON Schema Core)はその名の通りJSONの形式を表明する形式で、スキーマに基づいて入力の検証を行うためのボキャブラリを定義するJSON Schema Validationなどの仕様とあわせて利用されます。
以下、CoreとValidationをまとめてJSON Schemaと呼びます。
JSONと名がついていますがあくまでシリアライズ形式にJSONを選んでいるというだけで、利用する上でその他の制約はありません。
JSONとしてシリアライズ可能、すなわちJSONが定義する辞書構造 (object) とコレクション (array) のほかいくつかのスカラ値 (string, boolean, null) のいずれかで表現できる入力であればJSON Schemaで表明・検証できます。
先に述べた通り環境変数は名前と値がそれぞれ文字列である辞書構造なのでJSONとしてシリアライズ可能です。
以下はあるスクリプトが期待する環境変数のJSON Schemaの例です:
{ "title": "Schema of some script's environment variables", "$schema": "http://json-schema.org/draft-06/schema#", "type": "object", "properties": { "DEBUG": { "type": "string", "enum": [ "1", "0" ] }, "LOGLEVEL": { "type": "string", "enum": [ "0", "1", "2", "3", "4", "5", "6", "7" ] }, "PLACK_ENV": { "type": "string", "enum": [ "development", "test", "production" ] }, "PATH": { "type": "string", "pattern": "[^:]+(:[^:]+)*" } }, "required": [ "PLACK_ENV" ] }
先に述べたnumberやbooleanを期待する例がJSON Schemaで記述されています。
実際にこのスキーマを用いて検証を行ってみます。
Rubyとjson-schema.gemを利用します。以下のGistにコード例を示します:
実行結果の例です:
✘╹◡╹✘ < ruby validates_env.rb The property '#/' did not contain a required property of 'PLACK_ENV' ✘>﹏<✘ < PLACK_ENV=a ruby validates_env.rb The property '#/PLACK_ENV' value "a" did not match one of the following values: development, test, production ✘>﹏<✘ < PLACK_ENV=development ruby validates_env.rb ✘╹◡╹✘ <
PLACK_ENV=a
を渡したらきちんと怒られてかわいいですね。
独自実装を含む他の検証方法に比してJSON Schemaを選ぶ利点はいくつかあります。
一方、物足りないと感じる点としては、enumやpatternプロパティを駆使するほかなく、あまり可読性が高くない点でしょうか。
この点については、JSON Schemaの仕様ではformatプロパティに独自のキーワードを追加・利用することを許容しているため、booleanライクな文字列の定義を追加し、それをformatに指定することで冗長な定義を避けられるかもしれません。
Implementations MAY add custom format attributes. Save for agreement between parties, schema authors SHALL NOT expect a peer implementation to support this keyword and/or custom format attributes.
JSON Schema Validation: A Vocabulary for Structural Validation of JSON
以上、設定のスキーマをJSON Schemaで記述・検証することでコンテナ時代に即したtwelve-factor appパターンを促進する試みでした。
私はtwelve-factor appの環境変数を推進する姿勢については環境変数の表現力の乏しさを懸念し懐疑的でしたが、JSON Schemaを利用することを思い付いてからは懸念も解消され強く共感します。
既に述べたように独自formatを定義・利用するバリデータがあるとより便利かもしれないという思いもあるので、引き続き検討・導入していきたいところです。
この記事ははてなエンジニア Advent Calendar 2017の8日目の記事でした。
明日 (12/9) はid:ikesyoです、おたのしみに!
昨日書いてたコード、テストが落ちるけどわけがわからないので途方に暮れたけど、一晩寝て起きたらもしかしてこうでは? という気付きが得られて、出社して試したらうまくいった。
集中力は単に集中力と言われるのであらゆる対象に対して1つの共有のプールがあって、そこからリソースを奪い合うかのようなイメージだけど、意外とそうではなくて対象ごとにそれぞれプールがあって残量が0になると知性がなくなる、みたいなモデルなのかもしれない。
自分の中に集中力リソースが100あって、好きなタスクに100まで自由に注げるわけではなくて、集中力プールが5つあって、それぞれ20ずつ、みたいなかんじなのかもしれない。
だとすると、ひとつのことをずっとやっても集中できるのは20までなので、効率が悪い。最も効率よく働くには、集中力プールの数だけタスクをかけもちすればよい。
しかし集中力プールの数がいくつなのかは知らないし、使える時間は相変わらず共有リソースなのでどういう順番でやるかを考える必要がある。
あとタスクの進みが悪いときに他のタスクに手をかけるとなんとなく気まずさがある。
この世はままならぬ。
Release v0.4.0 · aereal/capistrano-strategy-jenkins_artifact · GitHub
capistrano-strategy-jenkins_artifactというgemを作ってメンテしており、これの0.4.0をリリースしました。
Travisのビルドでは最大約30倍速くなりました:
`bundle install` before: 126.69sec
Goodbye jenkins_api_client by aereal · Pull Request #21 · aereal/capistrano-strategy-jenkins_artifact · GitHub
`bundle install` after: 4.22sec
JenkinsのAPIを利用するためにjenkins_api_clientというgemを使っていたのですが、これはXML APIを利用することもあるので依存にnokogiriが入っており、`bundle install` に時間がかかるのがネックでした。
実際にこのgemで利用するAPIはJSON APIでまかなえたので、net/httpベースで書き直すことでjenkins_api_client経由のnokogiri依存をなくしました。ありがとうjenkins_api_client.
このgemはCapistrano 2 strategy that uses Jenkins' artifact as a distribution provider.
という説明の通り、Jenkinsのビルド成果物を取得するstrategyを提供します。
もともとはてなブログのデプロイ設定のために書いていたコードをgemとして切り出したもので、いまではMackerelなど社内のいくつかのサービスで導入されています。gem化してよかった。
ついでにOSS化したことでテストをちゃんと書こうというモチベーションが高まりお得。
ISUCON7 開催&日程決定! #isucon : ISUCON公式Blog
ISUCON7のオンライン予選にid:astjとid:tanishiking24の3人で秒速5000兆クエリというチームで出場した。最終スコアは9万ちょっとで、ベストスコアとほぼ同値だったので実力を出し切ったと思う。
ISUCONに競技者として参加するのは初めてで、エンジニアリングにスコアをつけて競い合うというのは聞いていた以上に楽しい。
ちなみに「競技者として初」というのは、昨年のISUCON6の参考実装の移植として関わっていたので、ISUCONと関わったという意味では初ではなかった。
2日前くらいにcatatuy/private-isuで練習した。振り返るとISUCON7の予選問題も画像をいかに効率よく返すかというところが最初のボトルネックで、早速予習が活きてお得。
pt-query-digestを使うとか、nginxのアクセスログを解析してボトルネックを見つけるとか、見つけたボトルネックの解消の分担だとか、タイムキープだとか、一通り押さえておきたいところは練習できたので事前準備は万端と言ってよい。
開始が遅れるとのことだったのでオフィスの近くにあるちょっといい肉料理のお店でランチをいただいた。
肉専科はふう 京都御所南の和牛ステーキを堪能できる洋食のお店
開始してからは、まず3人でレギュレーションの読み合わせをした。予選だけど複数台構成ということでおおっとなる。練習していた時のデプロイは雑にホストに入って `git pull` するだけだったけど、手間とかリスクを考えて早めにデプロイ整備をしようということになった。
ほか、ローカルとグローバルにそれぞれ帯域制限があることなどを確認しあった。この時点で参考実装は読んでいなかったけれどグローバル側が100Mbpsだったので、とにかくベンチマーカーから送られてくるリクエストを減らす = クライアントキャッシュを使うのが肝要というあたりをつけた。
読み合わせが終わってからはid:astjがSSH鍵のセットアップなどをしつつ、自分が初期プロビジョニング (mackerel-agentを入れたり、redis, memcachedを入れるなど) やデプロイ準備を進め、id:tanishiking24がkataribeのセットアップをしつつコードリーディングを進める、という分担になった。
レギュレーションを読み合わせましょう、とか、3人がどういう分担になるといいか、とかはISUCON本戦出場経験のあるid:astjに音頭を取ってもらった。普段からオペレーションも得意だしあてにはしていたけど、実際かなり頼りになり助かった。
id:tanishiking24も「じゃあこれよろしく」と振って危なげなく進めてくれるので、チームの並列度はマックスで最高だった。
練習でやったとおりnginxのアクセスログとMySQLのslow.logを見てボトルネックを1つずつ潰していく方針で進めた。
id:astjがやってくれたimage.nameにuniqueインデックスを張る変更でスコアが5万くらいに上がってテンションが上がってきたと思う。早いチームは早いうちからスコアを伸ばしていて内心やや焦っていたけど、同じ土俵に立てたことで安心しつつ、競い合えているなーと楽しくなってきた。
その後、N+1クエリを殺すなど分担してスコアをちまちま上げつつ、いよいよアイコンの配信をどうにかしないと帯域で当たってどうしようもない、という状態になって案を考えはじめた。
last-modifiedをつけてconditional GETさせよう、という方針になったのだけど、これはあとから考えると穴がある判断だったし、ハマる原因になってしまったな、と反省。
JSやCSSにはif-modified-sinceは来ているように見えたけどアイコンには来ていないので、last-modifiedヘッダの日付形式がおかしいのではないか、とか、304を返すロジックを間違えているのではないか、とか後から考えれば的外れな検討ばかりして時間が消えていった。たぶん3時間くらい費してしまったと思う。
最後のほうは本当にお通夜で、しかも大差ない変更をしたつもりだけどスコアが5万→3万→2万→3万とよくわからない上下をするので、一層お通夜が進んだ。
だんだん頭がおかしくなってきて、gzip圧縮かけているとstrong etagが毎回変わってしまいそれでキャッシュされていないのでは? ということになりgzipを切るなどしたが、効果はなし。
頭も朦朧としてきてヤケクソになって誰ともなくcache-control max-age=0とかつけてfailしなかったら儲けものじゃない? って話になり、ベンチマーカーを走らせるとなんと6万くらいになった。
その時のid:astjはこんなかんじだった:
,.へ ___ ム i 「 ヒ_i〉 ゝ 〈 ト ノ iニ(() i { ____ | ヽ i i /__, , ‐-\ i } | i /(●) ( ● )\ {、 λ ト-┤. / (__人__) \ ,ノ  ̄ ,! i ゝ、_ | ´ ̄` | ,. '´ハ ,! . ヽ、 `` 、,__\ /" \ ヽ/ \ノ ノ ハ ̄r/:::r―--―/::7 ノ / ヽ. ヽ::〈; . '::. :' |::/ / ,. " `ー 、 \ヽ::. ;:::|/ r'" / ̄二二二二二二二二二二二二二二二二ヽ | 答 | コ ロ ン ビ ア │| \_二二二二二二二二二二二二二二二二ノ
あとは初期データに含まれるアイコン画像を静的に書き出すのをやって9万 (ベスト値) が出る。……ものの、my.cnfを書き換えてベンチマークを走らせると5万くらいに落ちる→もう一度走らせる→スコア戻らず→変更を戻す……というようなよくわからないスコアの上下が相変わらず発生するので、最後の30分はベストスコアである9万を越えるまでひたすらエンキューする猿たちになっていた。結果、最後の10分くらいでベストスコア近いスコアが出たので、そこで打ち止めとなり終了。
普段やっていることに近いし社内の他のチームと感想戦をしあってみて、丁寧な配信最適化をやろうというかんじで、楽しめたし自分たちに足りていないところがあることを痛感させられ、たいへん楽しめました。
悔しくありつつも、初ISUCON参戦で楽しかったので、次は優勝したい。
予選参加することを決めたあとで10月22日に『響け!ユーフォニアム』のコンサートと被っていることに気がついて、慌てて21日の参加で問題ないか確認した時が一番肝が冷えた。
しばらく体調が悪く、週末になるとへとへとになる状態が続いている。
土日に休むとリフレッシュできて月曜日には元気一杯になるので、老衰による疲れやすさがあるにせよ、体力の最大値がそんなに大きく目減りしていることでもなさそうなので、今週は午後からの勤務として労働時間をだいたい50%にしている。
そしていまのところ調子がいい。いきなり気温が下がって身体に負荷がかかっているにしては、わりといい調子が続いている。
あとフィジカルというよりメンタルの負荷が大きそうで、午後に出勤するまでのあいだ、家の掃除をしたり洗濯をしたり、あるいはピアノを弾いたり、そういう時間が増えたことも大きいように思う。
つまりそういった家事や趣味をするぶんのフィジカルリソースの消費は変わらずあるものの元気というわけなので、メンタルリソースの消費が激しいという推論。
生涯で得られる幸福の総量について考えると、収入を2倍にするより労働時間を半分にするほうが総量は大きくなりそうだし、健康も保てて寿命が延びそう。