2016-09-19

[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 を使う必要はないと思ったので直接 MySQL を参照して取るように修正

15時
SPAM フィルタの部分が明らかに何か怪しいので、isupam を10個に増やして nginx の upstream に入れてもらったりしてテスト
とくに改善しないので全て元に戻す
キーワードと内容をくっつけて isupam に投げても問題なかったので、これでリクエストは減らせたので良しとする

16時
キーワード本文のキャッシュを追加 (htmlify の先頭で同じ内容のリンク済み内容が分かってればそれを返す、キーワードリストの変更があったら破棄する)
トライ木の Insert, Delete で差分更新を行えば、完全な再構築を回避できることが分かったので修正、これで画期的にスコアが上がる
再起動テストを実施、起動直後の初期化で MySQL につながっていなくてアプリがクラッシュする問題を発見したので修正

17時
ユーザー名をキャッシュするように修正
記事全件数をキャッシュするように修正

終わってから気づいた点
/ のスター取得部分のスター取得クエリが記事の件数と同じ回数流れちゃってるのは良くない
htmlify で []string 作って Join したが十分な長さの ByteBuffer でやった方が良かったのでは
isutar を廃止して、スターをオンメモリ化できたのでは

参加された方のレポート見て出来ていなかった点
キーワード本文キャッシュ破棄を全破棄ではなく上手くやる方法


関連リンク
[isucon] ISUCON5 予選敗退しました
ISUCON4 に挑戦して予選敗退しました

2016-01-26

[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 についての丁寧な説明が載っています。

2016-01-17

[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 に対して、エクスプローラーで閲覧したり、ファイルをコピーしたりすることが出来るようになります。

レジストリを閲覧するには、レジストリエディタ regedit で、HKEY_LOCAL_MACHINE を選択後レジストリハイブの読み込み機能で、例えば C:\shadowcopy1\Windows\system32\config\SYSTEM を適当な名前 system_shadowcopy1 で読み込み、中を閲覧することができます。不要になりましたらこのキーをアンロードすれば元に戻ります。

リンク
A simple way to access Shadow Copies in Vista - Antimail - Site Home - MSDN Blogs
レジストリにハイブを読み込む
[windows] 復元ポイントに保存されたレジストリを閲覧する (Windows XP用) - Windows Vista 以降では復元ポイントごとにレジストリがコピーされるわけではなく、ボリュームシャドウコピーの中に丸ごと保存されているようなので、以前の記事を更新しています。

2015-11-06

[Lawson] おさいふ Ponta に移行してみました

2015/11/3
おさいふ Ponta をローソンでゲットしたので、会員登録を行おうとしました。最初のステップで届くメールが Gmail の迷惑メールフォルダに分類されましたが登録自体は問題なく完了しました。旧カードからの移行は障害中だったのであきらめました。

2015/11/4
次の日の晩、復旧のニュースを見たので早速移行申請し、2015/11/5 の昼頃見てみたら移行完了していました。

感想
Ponta 部分は特に変更なく、発行の敷居の低さに反して JCB デビット自体の機能は十分と思います。

おさいふ Ponta マイページから暗証番号の登録と J/Secure (JCB の本人認証サービス) の有効化が行えるので設定すると良いと思います。

ローソン店頭でおさいふ Ponta 決済をするときは、カードを出した時点でおさいふ Ponta で決済したい旨を伝えなかった場合は、Ponta カードのスキャンだけして返してくれました。

個別の移行手順
ローソンモバイル Ponta
Android 端末内蔵の FeliCa に登録するローソンモバイル Ponta の変更はローソンアプリからログアウトして、かざすフォルダのおさいふポンタを削除、ローソンアプリで新 Ponta ログイン、ログイン時にモバイル Ponta 登録オプションを有効にして更新できました。
参考: 5. 機種変更する場合はどうなりますか?

リクルートID
リクルートIDとの連携は旧 Ponta 側をコネクト解除して、新 Ponta 側とコネクトしました。これは即座に完了しました。
参考: Pontaコネクトを解除するにはどうすればよいですか。

JMB×Ponta会員
JMB×Ponta会員は旧 Ponta 側でログインし連係解除を行った後、3日目にようやく新カードでの連携に成功しました。ここの連携は日次バッチ?のようなので気長に待つ必要があるようです。
参考: Pontaカードを2枚持っているが、JMBとの登録カードを変更したい場合はどうすればよいですか?

2015-09-29

[isucon] ISUCON5 予選敗退しました

ISUCON5 予選に土曜日の日程で参加しました。チーム名は円山町、チームメンバーは @ymz_kotaro と2人です。主にアプリの改良を担当しました。午後6時半ごろのスコアは12000点ほどで予選敗退しました。

予選当日の流れは大体こんな感じでした。

午前11時~午後2時
何もいじらずにベンチマーク実行、タイムアウトでFAIL。
my.cnf の設定すべき個所に右往左往しながら innodb_buffer_pool = 1G を設定してようやくベンチマーク通過。
GoAccess で nginx のアクセスログを解析してアプリ宛にしかリクエスト来てないと判断し、nginx の設定は放置することとする。
Ruby 実装のまま MySQL にスロークエリログ 0.1 秒を仕込んで pt-query-digest 見る、インデックスなしのクエリを発見したのでひとまずインデックスを修正。
Go 実装に systemd の設定を切り替えてテスト、ベンチマークはエラー多数で FAIL。
エラー原因を目視確認しようとするが見つけられず。試しに一度 go build -o app を実行して再起動すると動くことを発見。
3回連続でベンチマーク正常を確認したのでGo実装を使うこととする。

午後2時~午後7時
Go実装のアプリにデバッグ用サーバー net/http/pprof を組み込んで再起動する。ベンチマークを流しながら go tool pprof で CPU プロファイルを取得し、top50 -cum で関数プロファイル、list GetIndex で行プロファイルを取得して遅い部分を解析
プロファイル上時間がかかっているように見える N+1 クエリを修正。
users テーブルへの書き込みがないので初期化時に全体をロードするいんちきオンメモリ化を施す。
全て修正完了したと思っていた N+1クエリについて、テンプレート関数経由でデータベースアクセスしている部分を発見したので修正。
テンプレートエンジンを高速化しようと試行錯誤するがいまいち早くならず終了。

午後7時時点でやり残したと思っていた点
html/template の使い方でリクエストごとにテンプレートを解析していたので何とかする
gorilla/muxjulienschmidt/httprouter に交換

翌日の反省点
クエリごとに毎回 relations テーブルと JOIN せずに、友達一覧を先にとって、各クエリで再利用したほうが有効なことが GoBoldチームさんのコード を見て気づく
ローカルストレージ遅いと聞いてからデータの安全性を犠牲にする感じの MySQL の設定を試していなかったことに気付く

リンク
ISUCON公式Blog
hidekiy/isucon5q - app.go