投稿

[isucon] ISUCON7 本選17位でした

イメージ
2017年11月25日、LINE の新宿ミライナタワーの会場にて、 ISUCON7 本選にチーム 円山町(hidekiy, kotaroy, k_enoki) として参加してきました。成績は ISUCON6 本選と比べて若干の進歩はしたのですが、まだまだ上位層との壁を感じました。 当日やったことを書いておきます。 10:00~ SSH 鍵ログイン設定、Mackerel Agent 設定、Go 実装に変更、アプリの動作確認、Go の CPU プロファイル取得 (pprof) 12:00~ 分析の結果、初期状態のボトルネックは、DB と API のどちらの CPU, 各種 IO も使い切っていると言えないので、ロック競合か何かかと思ったが、煮え切らないまま深く考えなかった (これが致命的にまずかった) CPU プロファイル的には、多倍長整数演算が遅かったのと、コード上明らかにおかしな1000回ループ、テストコード付属という親切設計を見て、このループを最初に修理することにした。 16:00~ 初めて使う Go の多倍長整数演算ライブラリで、苦労の末1000回ループの除去に成功、それでも相変わらずボトルネックはDBのロックにあるように見え、これを何とか小細工しようとするが、特に有効な手を打てないまま時間切れとなった。 感想 速やかに、オンメモリー方式に作り替え、ロックを部屋別に分散させる決定をする必要があった。 Go の多倍長演算には結構苦しんだ。 糖を消費したせいか、ISUCON ケーキが美味しかった。 総括 素晴らしいイベントを企画、運営いただいた、LINE、KLab、さくらインターネット様には大変お世話になりました。ありがとうございます。

[isucon] ISUCON7 予選通過しました

ISUCON7 にチーム名 円山町 (@hidekiy, @kotaroy, @k_enoki) として出場し、去年に引き続き予選通過しました。当日について、記憶が定かな内にメモしておきます。 今回の予選問題について isubata という名前で、これは ISUCON 参加者になじみの深い idobata というチャットサービスを参考に作られているようでした。 用意したもの GitLab のプライベートリポジトリと権限設定 専用の Slack チャンネル Mackerel オーガニゼーションと公式プラグイン (inode, linux, mysql, nginx, proc-fd, uptime) の設定 ngxtop の使い方 2017/10/22 13:00 無事全員そろって開始 当日用マニュアル熟読 (@hidekiy, @kotaroy) 公開鍵ログイン設定と ssh config 作成 (@k_enoki) アプリのソースコードを GitLab へアップロード (@k_enoki) アプリを Go 実装へ切り替えと自動起動設定の修正 (@k_enoki) isubata アプリの動作確認 (@hidekiy, @kotaroy) インフラ構成と、nginx, MySQL の動作状況の確認 (@k_enoki) トラブルシュート用の mackerel-agent を全台に設定 (@hidekiy) 14:00 ローカル開発環境構築 (@hidekiy, @kotaroy) make deploy で全台にアプリがデプロイ (ローカルで GOOS=linux でクロスコンパイル後、scp して rename して systemctl restart) されるように設定 (@hidekiy) 静的ファイルの nginx 配信化と事前圧縮設定 (@k_enoki) DB のネットワーク上りがあんまりな状態だったので、一旦 image のオンメモリキャッシュを実装 (@hidekiy) /icon にインチキ Etag + If-None-Match 実装を試すが、全く 304 を返せず挫折 (@hidekiy) /profile の画像アップロード機能で、DB に二重に書き込まないように修正、ついでに...

[golang] crypto/rand で疑似乱数生成器を初期化する

Go 言語で疑似乱数 math/rand を使うとき、実行ごとに別の乱数列を選択するための方法として、rand.Seed(time.Now().UnixNano()) とするのが人気があるようなのですが、より予測困難さを追加するためには以下のコードのようにすると良いです。 今日では、Perl, Ruby, Python などで、明示的な seed をせずに rand を使った場合に、内部的に行われる自動的な seed では、OS の乱数生成器由来の値が使われるようになっているので、Go でも同じ感じで良いと思います。 package main import ( cryptorand "crypto/rand" "encoding/binary" "math/rand" ) func main() { randSeed() println("rand int:", rand.Int()) } func randSeed() { var seed int64 err := binary.Read(cryptorand.Reader, binary.LittleEndian, &seed) if err != nil { panic(err) } rand.Seed(seed) } LittleEndian は BigEndian でも良いです。crypto/rand には big.Int のインターフェースもありますが、こちらの方式の方が簡潔に書けると思います。 蛇足ですが、暗号化用の鍵や、何とかトークンのような、長さ分のエントロピーを持つ乱雑な文字列を作りたい場合は、math/rand ではなく、 crypto/rand をそのまま使う必要があります。 リンク math/rand: Deterministic random by default is dangerous #11871

ISUCON6 本戦敗退しました #isucon

22日土曜は第6回の ISUCON に参加しました。当日は無事起床は成功したのですが、完全に打ちのめされました。チーム名は円山町です。参加メンバーは会社の同期 @k_enoki, @ymz_kotaro です。今後のため当日やったことをメモしておきます。 10時~12時 4コア * 5台の構成が Azure のデフォルトのコア数制限にひっかかってデプロイ失敗、運営で2コア * 5台に変更していただき、この構成で競技することになる。 デプロイ後なぜかログインできないと思ったらユーザー名が自分の名前で入ろうとしていた。isucon@ としてログインに成功する。 バックエンド側アプリを Go 実装に変更後、何もいじらずにベンチ流してみるが、フロント側アプリの Node.js でアクセスログが出ていないのでアクセス状況は良く分からず。 12時~14時 Go のアプリのプロファイルを取得するためにアプリを改造する。Node.js 部分は @ymz_kotaro に依頼する。 @k_enoki が Node.js の前に nginx を立ててアクセスログを解析する。 isu05 に MySQL と Redis を立ててもらうのを @k_enoki に依頼する。 本番環境では別ノードの MySQL を使いたいが、ちゃんとした設定が良く分からないのでひとまずホストネットワーク設定とする。 docker-compose の扱い方でローカル環境構築に手こずったが、Docker for Mac ではホストネットワークが使えない問題があることが分かったので本番でのみ使うこととする。 14時~16時 docker-compose build していなくてイメージがリビルドされずコードの変更が反映されない問題を解決する。 Go のプロファイル上最も時間を費やしていた、あるルームの全情報を取得する API を Redis でキャッシュする機能を作成する。 ポーリングで沢山無駄にクエリを発行している、SSE で部屋の更新情報を通知してくれる API を Redis の Pub Sub を使って改造することを計画する。 16時~18時 Redis のキャッシュ機構はバグ修正を git pull してようやく機能するようになる。 更新情報通知用の Pub S...

[isucon] ISUCON6 予選通過しました

今回はついに予選通過しました。チーム名は円山町です。17日土曜日の予選当日にやったことをメモしておきます。 予選当日のタイムライン 10時 出社 (会社のオフィスから参加させてもらいました。大変感謝) 前の日の晩に作った無料試用アカウントでデプロイ Go 実装に変更、動作確認 記事を削除したら /initialize しても復活しなくて、初期データを壊してしまったので復旧方法を調査 /var/log/cloud-init-output.log を見て展開イメージの tar.gz を発見したので、中に入っている SQL ダンプでデータを復元 11時 Go 実装に切り替えたところ、スターが付かない不具合があったので、コードを検査、ngrep で調査して原因を特定 ローカルでコードいじるためにホームディレクトリで git init、必要そうなものを add/commit して push ローカルの MySQL にデータを入れて似たような環境を構築、バグ修正、動作確認 正常に動作するが、キーワードの置換処理があるページが遅くてベンチどころじゃないので、アプリに net/http/pprof を仕込んで、キーワード個別ページを叩いた時の CPU プロファイルを取得 htmlify の正規表現コンパイルと正規表現マッチングが遅いことが分かったので、何とかする方法を検討 12時 昼食、修正方針の検討 13時 htmlify で行っているキーワードの発見部分は、元上司の okzk さんが活用しているのを見たり、他プロジェクトのコードで見たことがあったトライ木で何とかするのが良さそうと判断、触ったことのあった github.com/armon/go-radix を使わせていただいて試作してみたところ、特に問題なく動き、動作はだいぶ速くなった。 ベンチを流しながらプロファイルを取ったところ、トライ木の構築に時間がかかっていたので構築済みのトライ木をキャッシュする (キーワードリストが変わったら破棄) ように修正 14時 isutar のスター追加処理でキーワードの存在チェックにキーワード個別ページを叩いていて迷惑なので MySQL から存在情報を取るように修正 isuda のスター取得部分で HTTP API を使う必要はないと思...

[windows] BitLocker の暗号化モードを新しい XTS-AES に変更してみました

イメージ
Windows 10 バージョン 1511 の新機能で、BitLocker の暗号化方式が追加されたので、早速変更してみました。 変更方法は、いったん暗号化を解除した後、再度暗号化をする際に、以下の画面の選択肢の中で「新しい暗号化モード」を選べばよいです。 ディスクがリムーバブルではなく内蔵のときはデフォルトで新しい暗号化モードが選択されていました。 GUI 上は暗号化方法を確認出来る画面が見つからなかったのですが、BitLocker のコマンドラインツール manage-bde を使うと以下のように XTS-AES が使われていることを確認できました。 C:\WINDOWS\system32>manage-bde -status BitLocker ドライブ暗号化: 構成ツール Version 10.0.10011 Copyright (C) 2013 Microsoft Corporation. All rights reserved. BitLocker ドライブ暗号化で保護可能な ディスク ボリューム: ボリューム C: [Windows] [OS ボリューム] サイズ: 475.98 GB BitLocker のバージョン: 2.0 変換状態: 完全に暗号化されています 暗号化された割合: 100.0% 暗号化の方法: XTS-AES 128 保護状態: 保護はオンです ロック状態: ロック解除 識別子フィールド: 不明 キーの保護機能: TPM 数字パスワード BitLocker の新機能 (Windows) - 公式のリリースノートのようなものがあります。 セキュアVMを支える暗号技術 - 筑波大学 セキュアVM開発室 面 和成 - XTS-AES についての丁寧な説明が載っています。

[windows] 復元ポイントに保存されたレジストリを閲覧する (Windows Vista 以降用)

管理者コマンドプロンプトにて、vssadmin list shadows、とすると復元ポイントごとの保存先アドレスが、項目「シャドウ コピー ボリューム」に表示されます。通常の復元機能では見えるコメント欄がないので、通常の復元機能の方で日時の当たりを付けておくと良いと思います。 出力例 Microsoft Windows [Version 10.0.10586] (c) 2015 Microsoft Corporation. All rights reserved. C:\WINDOWS\system32>vssadmin list shadows シャドウ コピー セット ID: {0000000-1111-2222-3333-444444444444} の内容 1 個のシャドウ コピー、作成時刻: 2015/12/26 8:39:27 シャドウ コピー ボリューム: \\?\GLOBALROOT\Device\HarddiskVolumeShadowCopy1 元のコンピューター: PC123 サービス コンピューター: PC123 プロバイダー: 'Microsoft Software Shadow Copy provider 1.0' 種類: ClientAccessibleWriters 属性: 恒久, クライアント アクセス可能, 自動リリースなし, 差分, 自動回復 しかしとてもアクセスしにくいので mklink でシンボリックリンクを作成すると便利です。mklink /d SRC DEST で、DEST 末尾の \ を追加で付ける必要があるので注意してください。 C:\WINDOWS\system32>mklink /d c:\shadowcopy1 \\?\GLOBALROOT\Device\HarddiskVolumeShadowCopy1\ c:\shadowcopy1 > \\?\GLOBALROOT\Device\HarddiskVolumeShadowCopy1\ のシンボリック リンクが作成されました この後は c:\shadowcopy1 に対して、エクスプローラーで閲覧し...