isucon4予選AMIが公開されたのでPHPでやってみた(score:54491)

前置き

人がやったことは見ないようにはしてたけど、

まあ概要知っちゃってるし、

合間の時間でやったために合計で何時間かかったかは

分からない(体感では実作業時間は合計10時間くらい)ので、

それなりに良いスコアが出ましたが、

自慢でもなんでもなく、ただの自己満であり、兼メモです。

 

やったこと

  • MySQL5.6への入れ替え&チューニング
    • MySQLの存在感がほぼ無くなったので意味無かったw
  • Nginxの細かいチューニング(参考
  • Sessionの保存先をtmpfsに移す
  • ついでに静的ファイルもtmpfsに移す
    • 再起動時に消えるとOUTなので、
      /etc/rc.localに移すコマンドを入れておく
  • トップページの静的ファイル化
    • 初めはプロキシキャッシュにしようとしたんですが、
      Session IDのSet-Cookieもキャッシュされるため(?)
      ダメだったので諦めました
    • ベンチマークではクエリストリングを見てなかったので、
      クエリストリングを目印に返す対象をrewriteする
  • php-fpmのプロセス数調整
    • プロセス数は固定
      pm=static
    • プロセスの再生成は行わない
      pm.max_requests=0
    • 結果的にはNginx、php-fpm共に
      CPUコア数(4)と同じプロセス数がベストだった。
  • Opcacheのスクリプト更新チェックや不要なオプションをOFFにする
    opcache.revalidate_freq=0
    opcache.validate_timestamps=0
    opcache.save_comments=0
    opcache.load_comments=0

  • データを全てAPCuキャッシュに載せる
    • login_logはINSERTはするけど、
      永続化が必須条件の最後の集計だけのために使う
    • login_logは単純に置き換えるのではなく、
      必要な形で集計した値
    • usersはそのまま
    • 初期化処理でDBに入るデータは、
      初期化処理の最後でAPCuに写す
  • APCuキャッシュによって、
    login_logは遅延書き込みが許されるようになったため、
    ENGINE=MyISAMにしてINSERT DELAYED文にして非同期化
  • 集計処理がタイムアウトするようになったので、
    少しだけインデックス追加

実際の設定ファイルやらソース

 

結果

[isucon@ip-10-175-1-202 ~]$ ./benchmarker bench --workload='8'
13:54:13 type:info message:launch benchmarker
13:54:13 type:warning message:Result not sent to server because API key is not set
13:54:13 type:info message:init environment
13:54:36 type:info message:run benchmark workload: 8
13:55:36 type:info message:finish benchmark workload: 8
13:55:41 type:info message:check banned ips and locked users report
13:55:43 type:report count:banned ips value:1033
13:55:43 type:report count:locked users value:5071
13:55:43 type:info message:Result not sent to server because API key is not set
13:55:43 type:score success:252250 fail:0 score:54491

 

ということで、

あと少しで、しばらくPHP書かなくなると思うので、

最後に腕試しを兼ねてやってみた。

実際に参加して、時間制限内に同じことができるかというと、

たぶん無理だけど、予選結果の中でも上位で、

PHP実装の中では一つ頭抜けたスコアが出せたので、

心置きなくPHP卒業(?)できますw

 

来年は相棒見つけて出たいなー

 


AttributesにHashを使いたくなったらLWRPにしろ(Chef)

本日の反省文です。ご査収ください。

 

元々、Cookbookを書く時に、

「AttributesにHashを使いたくなったらLWRPにしろ」

というオレオレルールがありました。

 

これは、Cookbookの再利用性を確保して見通しよくするために、

なんとなく決めた自分なりの基準の一つだったのですが、

今日(2014.10.09)、それを破った手抜きCookbookで問題が起きましたorz

 

Chefにはattributesを定義できる場所が色々ありますが、

それらはざっくり言うと以下の様な感じで扱われます。

(ソースを流し見して把握しただけなので、間違いがあるかもしれません。また、説明しやすいように若干正確な挙動とは異なっています。)

  1. それぞれで定義されているattributesをHash化する(というかそもそもHashみたいな感じ)
  2. それぞれのHashをそれぞれ末端まで再帰的にmergeする
  3. Hashの末端で被った部分は優先順位に応じて上書きする

参考までに該当箇所のソース

 

問題は上記の2の部分で、

nodesやらrolesやらenvironmentsで定義したattributesの中にHashがあると、

それは「末端」ではないので、上書きではなくmergeされてしまいます。

 

つまり、上書きしたつもりがmergeされていて、

Cookbookのデフォルトとenvironmentsで定義した値が合わさって、

余計な設定が入ってしまったのです。

 

補足:

Cookbokkを書き直さずに上書きさせたい場合は、

override attributesに定義すると、とりあえず上手く行きます。

 

ということで、最後にもう一度…

「AttributesにHashを使いたくなったらLWRPにしろ」

 

手抜きは本当に(・A・)イクナイ!!