2015年10月14日水曜日

ISUCON5のベンチを動かすメモ


ISUCON5の予選問題を動かしてみたいけどどうやったらいいのかよくわからん人用のメモ。

GCPアカウント作成~イメージ作成まではレギュレーションに書いてあるので省略。

$ sudo su - isucon
$ vi .bashrc

 //以下を追記
export JAVA_HOME=/usr/lib/jvm/java-8-openjdk-amd64
alias ll="ls -la"
alias vi="vim"
 //.bashrc反映
$ . .bashrc
 // リポジトリをクローン
$ git clone https://github.com/isucon/isucon5-qualify.git

$ cd isucon5-qualify/bench

 //ビルド
$ gradle compileJava

 //jq入れる
$ sudo apt-get install jq

 //ベンチ実行
$  ( curl localhost/initialize;cd ~/isucon5-qualify/bench; cat ~/isucon5-qualify/webapp/script/testsets/testsets.json  | jq .[0] | gradle run )

自分の環境ではなぜかベンチがJSTの時刻を取得できなくてうまく動いてなかったので、
以下の修正を入れた。

$vi ./bench/src/main/java/net/isucon/isucon5q/bench/scenario/BootstrapChecker.java
LocalDateTime beforeUpdates = LocalDateTime.now().withNano(0);
LocalDateTime afterUpdates = LocalDateTime.now().withNano(0);

 => 以下のようにZoneIdを指定
//ZoneIdをインポート
import java.time.ZoneId;

ZoneId zoneId = ZoneId.of("Asia/Tokyo");
LocalDateTime beforeUpdates = LocalDateTime.now(zoneId).withNano(0);
LocalDateTime afterUpdates = LocalDateTime.now(zoneId).withNano(0);


以上。

2015年9月27日日曜日

Excel系SEがISUCON5に参加してみた



ISUCONなる面白そうなコンテストがあったので、同僚を誘って計三人で参加してみた。
やったこと、感想などを残しておく。

1.ISUCONとは

お題となるWebサービスを決められたレギュレーションの中で限界まで高速化を図るチューニングバトル。 詳しくはこちら

2.準備編

今年6月ぐらいからISUCONが開催されることを知ったので、三週間に1回ぐらいみんなで過去門をやるぐらいのまったりペースで練習開始。普段こういうチューニングはやらいので、みんな手探りの状態からとりあえずスタート。最終的に5回ぐらい集まって練習会を実施し、行ったのは大体以下の内容。

  • 1回目・・・ とりあえずISUCON4予選過去問をやってみる。AWSの設定やら試行錯誤でみんな好き勝手にいじる。模範解答を参考にnginxやRedisを入れてスコアをあげてみる。
  • 2回目,3回目・・・ ISUCON4予選問題を各自でいじってみて、結果を持ち寄る。node + Redis構成にしてMySQLを完全に取っ払うことで、当時の予選通過スコアぐらいまで出せて満足。
  • 4回目・・・ ISUCON3予選問題をみんなでやる。そろそろ本番はどういう構成で望むのかを議論。みんなそれほど得意な言語はなかったので、最大公約数的にRubyを選択し、DBは部分的にRedisかもしくはSQLite(インメモリ)で行こうという方針で検討。
  • 5回目・・・ ISUCON4予選問題をRuby+Redis+nginx で構成するように模擬本番形式で実施。Google Cloud Platformで動くISUCON4予選イメージが配布されていたので、そちらを使用する。スコア送信用本番サーバ1台と、各自の開発用サーバ1台*3の構成で実施。ファイルの受け渡しはGithub上のリポジトリでやり取りするように取り決め。SSH鍵の作成やRuby, Redis, nginx の設定ファイルテンプレをリポジトリに登録。
# レギュレーションを見て、予選終了までリポジトリ公開は禁止だったので、慌ててgithubアカウントをプライベートに変更(合わせてGithubアカウントをアップグレード)

また、予選をチーム名"本業:Excel職人" で登録。

3.本番当日編

10開始予定だったので、9時に集合して買出しなど済ませ、準備に入る。
その後アナウンスがあり11時開始に変更となったので、それまで待機。ISUCON4のイメージを上げて復習。

11時からポータルサイトにアクセスが解禁され、VMイメージが公開されたので、早速展開して接続。その際に"uname -a" を打ったときに衝撃が走る。

Linux isucon5-production 3.19.0-21-generic #21-Ubuntu SMP
Ubuntuだと・・・(´゚д゚`)


ISUCON4予選も3予選もCentOSだったので、Ubuntuはノーマークだった。しかも普段CentOSしか触っていなく、Ubuntuをサーバ用途でいじったのは何年ぶりかわからない。
しかもサービスはsystemdで管理されているし。。これログどうやってみるんだっけ。。
※(追記) レギュレーションにUbuntuって追記されてましたね。。恥ずかしい。。

学生のころの期末テスト開始直後で問題用紙を裏返して見た直後に"ここ出すんかい"
と試験勉強範囲を外されたときと似た思いだった。

お題はSNS系のサイトだった。過去の予選に比べかなり複雑な印象を受けた。
DBのテーブルも今まで2~3個だったけど、今回は7つ。

とりあえず1時間半程度かけてみんなでコードリーディングしながら、改善点を洗い出していく。
最終的に変更できたのは以下の内容。

  • nginxでの静的ファイルのキャッシュ。nginxやunicornの稼動プロセス数の変更。通信のgzip化
  • tcp接続からunixドメインソケットを使用するよう変更
  • 足跡の処理をMySQL -> Redisに変更
  • 日記のentryテーブルのbodyカラムにタイトルと本文が入っているために、分離
  • usersとsaltsテーブルの統合
  • いけてないMySQLクエリを粛々と改善。インデックスの検討
  • 不要なサービスの停止
上記のことをやっていたらいつの間にか8時間たってしまった。
スコアは上位陣とは程遠いもので、初期スコアよりはまあ改善は見られるものの、もう少し出せればよかった。。上位陣の模範解答が気になる。

練習でやろうとしていたことは最低限できたような気がしたが、修正スピードが遅かった。
もう少し多くの部分をRedisに置き換えたかったが、ベンチに怒られて最終的にコミットできず。
また練習ではベンチマークがまわし放題だったが、本番ではベンチの実行リクエストがキューに
たまるので好き放題まわせなくて、修正に戸惑う場面もあった。

今回の練習でsinatoraとかnodeとかRedisとかnginxとか普段触らないものを勉強できたのでいい機会だった。
前回よりお題が複雑で、運営さんも大変そうだった。

似たようなイベントがあればまた参加したい。


※上記ロゴ画像は本家より拝借しております。問題ありましたら削除しますのでご連絡下さい



2014年6月9日月曜日

AndEngineの使い方(インストールメモ)

Andoridの2Dゲームエンジン"AndEngine"が面白そうなので、使い方をメモ




当方の実行環境は以下の通り。

  • IntelliJ IDEA Community Edition 13.1.2
    • Android開発用のプラグインを入れておくこと
  • 以下のバージョンのAndEngine
    • commit: 720897f99d2c56ba357e8fe361454bd8d88c37ed
  • AneEngineExample
    • commit: 75b657b2cd7e1153e005a917753b6d0390e034d5
  • その他GitHubに公開されているExtension全て

1.ソースコードの入手

Githubにソースコードが公開されているので、AndEngine本体に加えて、サンプルコードをExtensionをすべてcloneする。
同一のディレクトリにまとめてcloneしておくと便利。

2.プロジェクトの作成

IntelliJの"import project"でAndEngineExampleのプロジェクトをインポートする。
参照するライブラリはInnteliJが自動で解決してくれるみたい。便利。

3.サンプルプログラムの実行

ExampleLauncherを実行すればさまざまサンプルが実行できる。

そのままビルドすると、いくつかエラーが発生したので、以下のように修正





  • java: シンボルを見つけられません[シンボル:   クラス DrawMode




  • インポートするディレクトリを変更 

  • import org.andengine.entity.primitive.vbo.DrawMode; 
    → import org.andengine.entity.primitive.DrawMode;





  • TextBreakExampleのTextOptionの引数が逆になっているので修正



  • BoundCameraExampleのAnimatedSprite作成時に、animateの実行を別の文に分ける。
  • final AnimatedSprite face = new AnimatedSprite(pX, pY, this.mBoxFaceTextureRegion, this.getVertexBufferObjectManager()).animate(100);



    これでビルドできるようになり、
    これらのサンプルを参考にすればすぐにある程度ゲームが作れそう。


    2013年12月21日土曜日

    ブラックジャックのシミュレータをjavascriptで書いてみた

    ブラックジャックのシミュレータは以前も作ったことがあるけど、今回はブラウザでも実行できるようjavascriptで作ってみた。 途中で力尽きしまったので、ディーラーのシミュレーション部分のみ作成。 概要は以下のとおり

    • ディーラーのアップカードを2~10, Aceのいずれかを選択する
    • 17以上になるまでカードを引く
    • 最終的なディーラーハンドの出現回数と割合を計算する


    結果の見方

    たとえば、ディーラーのアップカードが10のとき、バーストする確率は約22~23%というが分かる。 ということは、プレイヤーカードが16であったとしてもスタンドすればほぼ8割方負けしまうので、引いた方がまだましという判断になる。

    シミュレータの場所

    シミュレータのページはこちら

    2013年8月31日土曜日

    BlackJackシミュレータ作ってみた

    ブラックジャックのそれぞれの手の場合にどれくらいの期待値で
    勝てるのかを調べるために、Scalaでモンテカルロシミュレーションプログラムを作ってみた。


    • プレイヤーの手札が8~20の時に対して、ディーラーのアップカードが2~Aのそれぞれに対して、HIT/STAND/DOUBLEDOWNを500000回繰り返したときの期待値を求める。
    • カードは無限にあるものとする(カウンティングの要素は含まない)
    • 乱数は擬似乱数を使用する
    • サレンダーは考慮しない(アーリーサレンダーとレイトサレンダーを分けるのがしんどいので)
    • ディーラーはソフト17スタンドとする

    結果



     こんな感じになった。表の各数値はHIT / STAND / DOUBLE DOWN をずっと繰り返したときの期待値です。各セル内の最大値となるものが、最適戦略となる。


    他のサイトとの比較

     このあたりに掲載されているベーシックストラテジーと比較すると、一部微妙に違いがあるが、このあたりは乱数の性能の限界なのかもしれない。




    作成したプログラム


    GitHubに置いています。

    2013年4月13日土曜日

    家に帰ってブログ書くまでがシェル芸



    春爛漫シェル芸人撩乱勉強会に参加してきた。
    本日はwget, curl, sedさんたちが活躍する内容。 curlなんて入ってたっけ?と思うぐらい何もしない状態での参加をしてしまった。
     前回と同じく以下、自分の知らなかったことの(断片的な)まとめ。

    curl, wget で画像URL収集

    curl, wgetでhtmlファイルを持ってきて、そこからは必要なデータを切り出すという作業。
    以下はimgタグにある画像データを取ってくる場合。

    $ curl http://www.yahoo.co.jp | sed -e 's/<img src/\n&/g' | grep "img src" | grep http | sed -e 's/^[^"]*"//' | sed -e 's/".*$//'
    
    http://k.yimg.jp/images/clear.gif
    http://k.yimg.jp/images/clear.gif
    http://k.yimg.jp/images/clear.gif
    http://k.yimg.jp/images/clear.gif
    ・・・以下略
    

    上のコマンドを見て気持ち悪いと持った人は正常な感性を持ってると思う。オレならこう書けるとか思った人は変態やと思う。

    ひたすらsedでテキストをいじってるけど、このURL抜き出しに必要なsedイディオムは以下のようだった。
    • img srcタグ1つにつき1行にするように抜き出したいタグ(この場合img)の前に改行をぶちこむ
    • 先頭からURLの直前の'"'までと、URL以降を削除する。
    正規表現は普通に書くと最長一致となり意図しない部分まで削られてしまうので、 ^[^"]*"のような気持ち悪い書き方になる。これは何とかならない物なのか。

    grep -oオプションを使えばもう少し簡単にかけて、以下のような感じになった。
    $ curl http://www.yahoo.co.jp | sed -e 's/<img src/\n&amp//g' | grep "img src" | grep -o 'http://[^"]*"' | tr -d \"
    
    
    
    -oオプションは行単位ではなく、マッチした部分のみ出力する。これは一番明日から使える内容かもしれない。 

    いずれにしろ、こういう書き方はワンライナーだから許されるものであってこんなのがスクリプトとして残っていたら見るほうが発狂しそう。

    あと便利なgrepオプションついでに-A -B -C (NUM)オプションも素晴らしい。これはマッチした行の前後もあわせて表示すると言うもの。

    % seq 1 10 | sort -R
    % seq 100 110                                           
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    
    # マッチした次の行も表示
    % seq 100 110 | grep -A 1 105
    105
    106
    # マッチした前の行も表示
    % seq 100 110 | grep -B 1 105  
    104
    105
    # マッチした前後の行も表示
    % seq 100 110 | grep -C 1 105 
    104
    105
    106
    
    


    curl, wgetでPOSTリクエスト

    以下のようにすれば、wget, curlでもPOSTリクエストが送れる。 cronで定期的にリクエスト投げたいときに使えるかもしれない。
    $ wget -O - --post-data=test http://www.usptomo.com/XXXXXXX
    $ curl -d test  http://www.usptomo.com/XXXXXX
    
    

    他にもいろいろあったけど、とりあえず酒が入ってものすごい眠いので今日はここまで!