タグ: php

ISUCON7予選に参加したお話

結果から先にお伝えしますと、予選通過できませんでした。

そして今頃振り返ることにしました。

まとめ

会社の先輩方と ( @kopug, @dabits ) チーム「TMFusion」として参加しましたが、1日目、2日目のマージ後ランキング 32位 (スコア: 96,576 )  で予選通過出来ませんでした。

そんな私が、前日までにやったことと、当日やったことをさらっとまとめます。

事の発端

@chimame さんが、FacebookにISUCONについて9月頭に投稿したのが始まり

CTO始め、有志が集まりプロジェクト(なのかわかりませんがw)が始動しました。

CEO始め、参加しない方々からもいい意味でプレッシャーをかけていただき。合わせて、オフィスが名古屋、大阪と別れている事もありチームによってはリモートで予選を行う事も考えられましたが移動のための交通費も会社が負担して頂けることに。様々な大人の方にバックアップ頂いた中、結果が出せず非常に悔しい思いです。

前日までにやった事

ISUCON前日までは、ひたすら過去問を行いました。

一番最初に行った過去問は去年の予選でした。(マシンスペックにもよりますが)約200点台と非常に低かった事で火がついた事は鮮明に覚えています。

ある過去問のベンチマークアプリケーションの不具合に悩まされたり、goは書いていたので気分転換にgoに手を出したらドハマリしたりと今となってはいい思い出です。

今回事前に説いた過去問は以下を行いました。

  • ISUCON6 予選
  • ISUCON5 予選
  • pixiv ISUCON
  • yahoo ISUCON

ちなみに、ISUCONの予選は会社の制度を使わせて頂き予選前の3週間は15時位からチームで集まって過去問を解くようにしていました。

また、今回使用しようチームで決まっていた言語はPHPでしたのでおそらく使われるであろうSlimFrameworkのドキュメントを入念な確認も行いました。

それに合わせて、ルーティングキャッシュや、テンプレートキャッシュ、リクエストヘッダのログ出力、OPCacheのリセットスクリプト、デプロイスクリプト等ある程度予測が出来、使用確度が高いものはすぐ適用できるようにスニペットに用意しておきました。

加えて、当日の役割分担やISUCON環境をぶっこ抜くScriptをつくったりと楽しみながら且つ着々と準備を行なっていきました。

当日の事

当日は、そもそもしっかりと運営の案内に目を通していなかったので目を通すと共に、Discordにも入っていなかったりとバタバタしながら準備を行いました。

皆さんご存知の通り開始が大幅におくれたこともあり、別の所に用意していたGitlabのスニペットに使用するであろうコード等を移動させ複数画面を行き来せずとも快適な環境をつくることとしました。

また、待っている間のDiscordでのみなさんとのわいわいは、特別な空気感もありとてもたのしかった印象です

(気になったのでアニメを全く見ない私ですが終わってから、ちゃんと「NEW GAME‼︎」をプライムビデオで見ましたww)

前置きはさて置き、協議中のことも書こうかと思います。スタートの合図とともに、アプリケーションを担当した私が行った事を順に挙げると

  • サーバー構成の確認
  • ソースコードをバージョン管理下に置きソースの確認
    • 合わせて、方針や改善ポイントの洗い出しや順位づけ
  • ベンチマークの実行
  • スニペットに用意しておいた、リクエストヘッダのログ出力コード・Slim Frameworkで用いるルーティングキャッシュ・Viewキャッシュのコード適用、デプロイスクリプトの配置

ざっとここまでを1hちょっとで行いました。

その後に、DBに入っていた画像を外だししたり、initializeのときにメモリに乗っけられるものは全部乗っけるようにしてみたり、ISUCONのアプリケーション側で行う定石をつぎつぎに行っていきました。

ただ、うまく行かなかった点として、インフラとアプリケーションの連携がうまく行かなかったことです。何がうまく行かなかったかというと、DBに入っていた画像を外だしした際に何故かスコアが下がる現象が発生し、3人共何が悪いのかさっぱりわからなくなったことが発端となり、一旦全部もとに戻そうとインフラもアプリケーションも初期状態までロールバックしその後今まで行ってきた変更を1つずつ反映していくということを行いましたw

これがものすごく時間を食ったことに加え、このときばかりは少しチームの雰囲気も悪くなってしまったように感じました(普段はそんなこと無いのですが)

そんな、こんながありましたが、「96,576点」まで行くことが出来ました。

ちなみに、ベンチマーカーの複数選択出来る仕様であることをしらず、非常に悔しい思いをしました。ちなみに、複数選択出来ることを知ったのは、振り返りのお酒の場でした。自分たちのチームメンバーだけではなく、競っていた社内の他チームも知らなかったとのことなのでもしかしたら予選通過出来ていた可能性もあると考えると非常に悩ましいですし、なぜ複数チェックを入れなかったのか予選中の私をすこし攻めたい気持ちもあります。

良かったこと

予選前に、過去問や他社さんが公開しているISUCONを行うことによって予選時に特に慌てることなくいい感じに早くすることに注力出来たのかなと思います。また、ここでの取り組みが少しずつではありますが、業務にも生きているように感じています。

加えて、予選だけではなく当日の進め方や、事前にレポジトリ作成を始めとする準備をしっかり行っていたこともあってか、よりPHPerの私としては知識であったり知見が多く得ることができたのかなぁと思います。

何事も準備って大切ですね

また、私転職したばかりで、同じチームの人とコミュニケーションはありましたが、ほかチームとはなかなかコミュニケーションだったりを取れていませんでしたが、ISUCONの取り組みを行うにあたって、コミュニケーションの輪が広まったように思います!

チームとしての課題

チームとしての課題は明確に1つコミュニケーションだと考えています。当日の事にも記載した通り、チームで壁にぶつかった時こそ一呼吸おいて動くようにするなどするべきだったのかなと今になって思います。

私の課題

私の課題としては、今回アプリケーションに専念させていただきながらももう少しインフラ側をどうするか等、積極的に首を突っ込むべきだったと思っています。

日常の業務でもそうですが、範囲に区切りをつける事は重要ですが、あくまで区切りは目安であって制約ではありません。

私は◯◯だから、△△だけやろうではなく、□□に対しても、◯◯だからこそ出来ることがある事は確かではないかと思います。

偉そうなことを書きましたが、私のインフラに関する知識不足が1つの原因である事は確かなのでこちらは今まで以上に努力しようかなと考えいます。

まとめ

反省点も多いですが、今回予選参加に当たって知識として多く身につけられた事は非常によかったと思っています。

また来年も参加したいなと思っていますのでコツコツと技術を磨き来年こそは本戦で花を咲かせたいなと思ってます!

そして、運営の皆様お疲れ様でした!

CakePHP2でMySQLのGeometry型を扱う

CakePHPでGeometry型を用いた
位置情報に基づいた検索を行う方法です

大事なこと

最初に言っておきます

CakePHPはGeometry型を用いた取得
には標準では、対応してません

なので取得保存にはちょっと
手順を踏まないといけないです

その前に

詳しくGeometry型について知りたい人は
以下から確認してください
[http://dev.mysql.com/doc/refman/5.6/ja/gis-class-geometry.html](MySQL :: MySQL 5.6 リファレンスマニュアル :: 11.5.2.2 Geometry クラス)

やってみた

データベース

まずデータベースとテーブルを用意しましょう
SQLはこんな感じです

CREATE DATABASE hoge;

USE hoge;

CREATE TABLE IF NOT EXISTS `geometries` (
    `id` int(11) NOT NULL,
    `hoge_id` int(11) NOT NULL,
    `latlng` geometry NOT NULL,
    `created` datetime NOT NULL,
    `modified` datetime NOT NULL
) ENGINE=MyISAM  DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ;

モデル

次にモデルを用意

ここで保存した際にGeometry型に変換されるように
beforeSaveの所に記述する

virtualFieldも用意しておきましょう
そうするとあとで楽なので

<?php class Geometry extends AppModel {

    function beforeSave() {
        $lat = $this->data['Geometry']['lat'];
        $lng = $this->data['Geometry']['lng'];

        $latlng = $this->query("SELECT GeomFromText('POINT($lng $lat)') as latlng");
        $this->data['Geometry']['latlng'] =     $latlng[0][0]['latlng'];

        return true;
    }

    var $virtualFields = array(
        'latitude' => X(latlag),
        'longitude' => Y(latlng)
    );

}

コントローラー

次にコントローラーでデータを取り出す方法
最初にも書いたとおりいつも通りのCakeの書き方じゃ取り出せ無いです。

でも基本は同じなのでいつもどおり書けばOKです

<?php class Geometries extends AppController {
    public function get_geo() {
        $geo = $this->Geometory->find(
            'all',
            array(
                'fields' => array(
                   // ここを変える
                ),
                'order' => array(
                    'let' => 'ASC'
                ),
            )
        );
    }
}

気をつけて欲しいのがfieldsのところに条件を与えることです
検索条件だからconditionsのところに条件を与えるとハマります

与えられた位置情報から近い順に情報を取得する場合は
こんなかんじに書きます

 GLength(GeomFromText(CONCAT('LineString(".経度." ".緯度.",', X(latlng), ' ', Y(latlng),')'))) AS let

ここの部分を変えれば2点間の距離を求めたり4点の位置に含まれる情報を取得することが出来ます

PHPでブラウザ・デバイス判定をする

ブラウザとデバイス判定する必要があったため
PHPでブラウザ・デバイス判定するコードを書いてみました。 

使用している関数などは公式ドキュメント PHP.net  を参考にしてください

実行環境は PHP 5.5.6 です
対応確認済みブラウザは

  • Internet Explorer  ~11
  • Google chrome  ~ 34
  • Firefox ~ 30
  • Opera ~ 22
  • Safari ~ 7.0
  • Sleipnir ~ 7
  • Konqueror
  • Dreampassport
  • BTRON
  • iCab
  • OmniWeb
  • Netscape

の12種類

対応確認済みデバイスは

  • iPod
  • iPhone
  • iPad
  • Andriod
  • Windows Phone
  • Blackberry
  • Linux
  • Mac
  • Windows

の9種類です

 ソースは以下URLにあります

mziyut/BrowserAgent · GitHub