« 2010年12月 | メイン | 2011年2月 »

2011年1月28日

都市伝説の検証!Flash CS5のswfはCS4よりファイル容量が大きい!?
このエントリーをはてなブックマークに追加 このエントリーをlivedoorクリップに追加

flashエンジニアのnaoです。

ディスカバリーチャンネルの番組に「怪しい伝説」(Mythbusters)ってのがありますよね。そう、"ワイヤーが切れて自由落下するエレベーター、地面に衝突する寸前に中でジャンプしたら助かるんじゃね?"とか、あほう 希少な検証をやるあの番組です。
ちょっと考えればわかりそうな事を真面目に検証する彼らを生暖かく見守る私ですが、この度自分自身、都市伝説に遭遇いたしました。
その都市伝説というのが、標題の「Flash CS5のswfはCS4よりファイル容量が大きい!?」なワケであります。


私の所属するプロジェクトでは、前任のflashエンジニアがFlash Profesional CS4で開発を行い、私を含めた後任のチームはCS5で開発を行っております。
この時に、前任からの引き継ぎ注意事項として

『swfファイルはCS4で書きだしたほうが軽くなる』

という物があり、実際に前任から引き継いだflaファイルでswfを書きだしてみると、本当にCS5とCS4で容量が違ったのです。CS5で書きだしたswfは、3KBほど容量が重い。
なにこの怪奇現象こわい
flash liteを利用する製品では、3KBは命取りです。
臆病風に吹かれまくって天高く舞い上がった私は、CS4のライセンスを持っているチームメンバーに依頼して書き出しをしたのですが、上空の偏西風に流されてミッドウェイあたりまで来たところで、はたと気が付きました。

同じ処理をしている100KB程度のバイトコードで、3KBもサイズが違うのって、明らかにおかしくね?

100KBのうちの3KBといえば、全体の3%である。1989年に導入された当時の消費税率と同じである。当時の消費税の税収は、なんと6兆円!まぁ、金額は関係ないのですが。

flashのバイトコードは、1処理で2バイトとか3バイト程度。それに変数名が付いたって、ActionScriptの1行分の処理でもせいぜい数十バイトである。いったい、どこで容量が増えるのだろうか?

【実験1】
まず私が試したのは、diffコマンドによって差分を比較する実験。swfファイルの差分を取って比べてみたら、何かわかるのではなかろうか、と思ったのですが、この実験はあえなく失敗。考えてみたら、バイナリの状態のコードなんて人間が一覧して分かるわけがない。実験以前に問題だった。Mythbustersを哂えない。


【実験2】
次に行ったのは、swfmillをインストールしてswfファイルをテキスト化し、再びdiffを取る実験。こちらは成功。そらそうだ。
内部の構造を追っていくと、ActionScript部分は変化がない。しかし、途中で謎のベクタ描画のグラフィックスオブジェクトに遭遇する。CS4には存在しない。CS5で書きだしたswfにのみ存在するオブジェクトなのだ。犯人のしっぽをつかんだ


【実験3】
初心に返り、Flashで書き出す際にファイルサイズのレポートを出力してみる。グラフィックスオブジェクトが書き出されているなら、何か記述されているはずである。
しかし、全てのオブジェクト名をチェックしたが、見覚えのないオブジェクトは存在しない。


【考察】
・ActionScript部分の変化は観察されない
・内部に謎のグラフィックスオブジェクトが挿入されており、これがファイルサイズ増の原因らしい
・しかしサイズレポートには怪しいオブジェクトは記述されていない


さて、この謎のグラフィックスオブジェクトは何か。レポートには名前も出ない存在だけのデータである。が、よくよくサイズレポートを見ているうちに、重大なものに気がついた。

なんと

デバイスフォントが埋め込み処理されている


のである。


-再現イメージ-

_等幅 : 確たなデりなまタ認しくー

いやいやいやいや、ないわー。完全にFlash Profesional CS5のバグである。
原因がわかれば対処方法も簡単。埋めこまれてしまっているなら、再定義してやればいい。
今回は以下のような手順で修正を行いました。


・デバイスフォントを指定しているテキストボックスを選択
・別の日本語フォント(_明朝でも何でもいい)に変更する
・全部のデバイスフォントのテキストボックスで上記を行う
・ファイルを保存して閉じる
・ファイルをもう一度開く
・全部のデバイスフォントのテキストボックスを、もう一度、等幅などのデバイスフォントに戻す
・保存して閉じる

以上である。すみませんね、手動作業で。
回避方法はあるかもしれないけど知りません。だってもう、私の環境では関係ないから。

書きだしたswfファイルは、みごとCS4で書きだしたswfと完全に一致しました。
現在では無事、CS5で開発を行っております。
なお、この不具合はCS4で編集したファイルをCS5で読み込む場合に発生します。
一度対応するか、初めから CS5で製作されたファイルでは発生しません。

こうして、Flash CS5のswfはCS4よりファイル容量が大きい!?疑惑は嘘っぱち(まぁバグっぽい物ではあったのですが)都市伝説と証明され、事なきを得ました。
何事も検証してみることが大事だよね☆

都市伝説の例
あやしい!と思った人は検証してみればいいと思うよ。

Mythbusters: Collection 1 [DVD] [Import]
Discovery Channel (2007-05-22)
売り上げランキング: 79419

2011年1月24日

iPhone向けのサイトを作るときのちょっとした気配り
このエントリーをはてなブックマークに追加 このエントリーをlivedoorクリップに追加

yamaokaです。

だいぶiPhoneやAndroidといったスマートフォン向けのwebページを作ることが増えてきたのではないでしょうか。ちょっとした気配りで使いやすくなるケースもあるかなと思うので、いくつか使えそうな工夫について書いてみたいと思います。

ただし、今回はiPhone向けです。

タップされた場所をハイライトする

iPhoneのSafariでは「-webkit-tap-highlight-color」という拡張された属性があり、タップされた箇所に色を付けることができます。CSS3ではRGBaによる色指定ができるので、半透明の色を指定すればタップされた箇所をわかりやすく示すことができます。例えば、

-webkit-tap-highlight-color:rgba(255,0,0,0.40);
と指定すると薄い赤色を付けることができます。「outline:none;」と併せてリンク文字列に指定するといいかもしれませんね。

数字を電話番号のリンクにしない

iPhoneのSafariはHTMLに含まれる数字を電話番号として検出、自動的に電話番号のリンクにしてしまいます。タップすると電話がかけられるので便利な場面もあるのですが、「123.45」のような小数点を含む数字や「100-0001」のような郵便番号、「2001-2011」のようなcopyrightの年号表記までリンクになってしまうのです。

この挙動を無効にするには

<meta name="format-detection" content="telephone=no">
とmeta要素を使って記述します。どうしても電話番号を表示したい場合は明示的にtelto:で指定してあげればいいので自動検出は無効にしてしまうのがオススメです。

文字のサイズをコントロールする

PC向けに作成されたサイトをiPhoneで見た場合、フォントの大きさがPCで表示した場合と違った比率で表示されることがあります。iPhoneのSafariは文字の大きさを自動で調整してくれるのですが、自分でコントロールしたい場合もあるのではないでしょうか。

自動調整を無効にしたい場合、CSSで

-webkit-text-size-adjust:none;
を指定します。先程の「-webkit-tap-highlight-color」と同様、iPhoneのSafariで拡張されているCSSの属性です。ただし自動調整がされなくなってしまうので、Media Queryなどを使ってスクリーンの大きさにあったfont-sizeを指定してあげる必要があります。

自動調整を無効にした場合でも、画面の向きが変わってローテートされた場合の表示の調整は行われます(iPhoneの場合)。

また、あえて自動調整にまかせるという選択肢もあると思うので、この属性を使用する場合はきちんとサイト全体の方針を決めてから使うのがいいのではないかと思います。

終わりに

iPhone向けの小さなtipsを3つ紹介しました。小さな画面で操作することが多い分、ちょっとした気配りで操作性が上がることも多いのではないでしょうか。少しでも気の届いたページを作っていけたらいいなと思います。

SafariのHTMLとCSSについてはAppleのリファレンスを見れば載っているので、参考にどうぞ。

2011年1月12日

WebエンジニアにやさしいYamahaルータRTX-*** 設定方法(導入編)
このエントリーをはてなブックマークに追加 このエントリーをlivedoorクリップに追加


こんにちは。入社6ヶ月目のyusukeです。

Webエンジニアの方がルータを触る機会は、少ないと思います。
ということで、Yamahaルータを例にルータの設定方法を紹介します。

1. Yamahaルータへのログインについて

Yamahaルータへのログインは、通常以下の2つの方法いずれかでログインします。

- シリアルコンソールケーブルを使用したログイン

シリアルコンソールケーブルを直接Yamahaルータに接続します。
シリアルコンソールケーブルはクロスケーブルとDSUB9 or 25 と RJ45 変換コネクタでも自作できます。(ルータの購入時に付属している場合もあります。)

- telnetまたはsshを使用したログイン

これは、ご存知のようにtelnetコマンドやsshコマンドを使用したログインです。

いずれもログインした後の設定方法は同じです。

ログイン時パスワードを入れてログインしますが、設定を行うには

以下のコマンドを入力して管理者モードに移行してから行います。

 $ administrator

2. お勧めする初期設定

- コンソールの表示文字コードを設定する

 $ console character ascii

文字コードを設定します。euc, sjisなどにするとエラーなどが日本語になったりします。

- コンソールの表示行数のリミットを外す

 $ console columns infinity

show ** 等でページ送りをしないように設定します。
show configコマンドなどを一度に表示して保存する場合などに最適です。
ページ送りを行いたい場合は、show ** | less で行えます。

- プロンプトの設定

 # console prompt zynga

これは、プロンプトの先頭文字列を設定するコマンドです。(例: zynga$ )
bashなどの$PS1と同じようなものです。ただし、特殊変数などは使えません。

3. コマンド入力記法について

- showコマンドとクエスチョンマーク( ? )

自分の設定した内容を見るときは $ show configと入力します。また、設定内容と現在の動作状況を見るときは $show tech または $show techinfoと入力します。
その他、show コマンドを入力後 ? を入力することでヘルプが表示されます。

- noコマンド

 $ no console character ascii

今まで、入力したコマンドを無効にしたいときなどに使用します。
show configで表示されるコマンドの先頭に no をつけて実行することにより該当行のコマンドが無効化または、デフォルト状態に戻ります。

- 設定の一括投入

一度に行う設定が複数ある場合、設定の反映はコピペで一括で行うことができます
初期設定時やネットワークを遮断した際の設定は一括で行った方が効率がよいと思います。
今までの設定は以下で行えます。管理者モードで以下3行をコピペすることで反映されます。

console character ascii
console columns infinity
console prompt zynga

- 設定の保存

 # save

設定内容を不揮発性メモリに保存して、ルータの再起動後でも設定が残るようにしておきます。

最後に、オンラインでの設定変更は十分にマニュアルや設定例などを読んだ上行ってください。予期せぬ再起動。通信断を招く可能性があります。

Zynga Japanでは積極的にエンジニアを採用しています。
採用ページをご覧になり、興味のある方はぜひご応募ください。

2011年1月11日

30分でわかる PHP Extensionの作り方を学べる記事をかいたよー \(^o^)/
このエントリーをはてなブックマークに追加 このエントリーをlivedoorクリップに追加

こんにちは。12月に入社した@chobi_eです。

私が所属しているチームではお菓子系男子が30%を超えているという素敵チームで 毎週チーム内の漢の子がお菓子を焼いてくるという状況でハッピハッピハッピーです。

今日は私が学んできたPHP Extension作成についてのノウハウの一部を 公開しようと思います。

PHPExtension作成についての資料はklabさんやyoyaさん rskyさんの記事が参考になりますが私のようにPHPは書けてもCが書けない人には具体的にhello world以降何をすればいいのかがサッパリよく分かりません。

そこで先人達が作ってくれた偉大なライブラリをPHPで扱えるようにする為にC/MigemoのPHPバインディングを作ってみましょう

C/Migemoをインストールしてみる

読者の方の中にはC/Migemoをご存知でない方もいらっしゃるかと思いますので簡単に説明するとC/MigemoはKoRoNさんが作成されているローマ字のまま日本語を(インクリメンタルに)検索する」ための正規表現を生成するライブラリです。

http://www.kaoriya.net/#CMIGEMO

私は普段Ubuntuで開発をしているのでUbuntuでのC/Migemoの導入方法の説明を書きます。 OSXやWindowsの方はC/MigemoのREADMEを読みつつコンパイルしてください。

sudo aptitude install nkf

svn co http://cvs.kaoriya.net/svn/CMigemo/trunk migemo
cd migemo
./configure
make gcc

make gcc-dict
cd dict
make utf8
cd ..
sudo make gcc-install

これでC/Migemoのインストールが完了しました。C/Migemoには簡単な動作を確認する為の プログラムが付属しているのでそれを使って試してみましょう。

cmigemoを起動してchobiという文字列を入力してみます。

chobie@air:~/src/migemo$ cmigemo -d /usr/local/share/migemo/utf-8/migemo-dict
migemo_open("/usr/local/share/migemo/utf-8/migemo-dict")=0x820d008
clock()=0.210000
QUERY: chobi
PATTERN: (チョビ|チョビ|ちょび|chobi|chobi)

chobiに対応した正規表現が生成されましたね!

PHP Extensionの下準備

まずはPHP Extensionの設計を自分がよく理解できる言語でふわっと書いてみましょう。

<?php
/**
* これは実装するExtensionの目標で実際には使いません。
*/
class Migemo{
    public function __construct()
    {
      //migemoのロードを行う
    }

    public function query($query)
    {
      //migemoに問い合せて正規表現を返す
    }
}

せっかくなのでUnitTestも書いておきましょう。

PHPExtensionを作成する場合は別途テスト用のrun-test.phpというのが付属してるんですが、自分で使う分には慣れ親しんだツールを使ったほうが楽なので今回はPHPUnit3を使います。

sudo pear channel-discover pear.phpunit.de
sudo pear channel-discover components.ez.no
sudo pear channel-discover pear.symfony-project.com
sudo pear install phpunit/PHPUnit

テストを書きます。

  • MigemoTest.php
  • <?php
    class MigemoTest extends \PHPUnit_Framework_TestCase{
    
    
        /**
         * Migemoロードされているかしらべるよ
         */
        public function testMigemoIsLoaded()
        {
            $this->assertEquals(true,extension_loaded("migemo"));
        }
    
        /**
         * Migemoクラスがあるかしらべるよ
         * @depends testMigemoIsLoaded
         */
        public function testMigemoClassExists()
        {
            $this->assertEquals(true,class_exists("Migemo"));
        }
    
        /**
         * @depends testMigemoClassExists
         */
        public function testQueryMethodExists()
        {
            $reflection = new \ReflectionClass("Migemo");
            $this->assertEquals(true,$reflection->hasMethod("query"));
        }
    
        /**
         * @depends testQueryMethodExists
         */
        public function testQuery()
        {
            $migemo = new Migemo();
            $this->assertEquals("(チョビ|チョビ|ちょび|chobi|chobi)",$migemo->query("chobi"));
            unset($migemo);
        }
    
        /**
         * @depends testQuery
         */
        public function testQueryCycle()
        {
            $migemo = new Migemo();
            for($i = 0; $i < 30; $i++){
                $this->assertEquals("(チョビ|チョビ|ちょび|chobi|chobi)",$migemo->query("chobi"));
            }
            unset($migemo);
    
        }
    }
    

    さて、これでExtension作成までの準備が出来ましたのでサクサク書いていきます。

    PHP Extensionを書く

    私は容量悪い系の人間なのでコツコツ書いてきますよ!みなさんも写経についてきてくださいね

  • config.m4
  • PHP_ARG_ENABLE(migemo,
      [  --enable-migemo      Enable "migemo" extension support])
    
    if test $PHP_MIGEMO != "no"; then
      export CFLAGS="$CFLAGS -lmigemo"
      PHP_SUBST(MIGEMO_SHARED_LIBADD)
      PHP_NEW_EXTENSION(migemo, migemo.c, $ext_shared)
    fi

    phpizeというビルド環境をチェックしつつコンパイルに必要な設定を書いてくれるconfig.m4というマクロファイルを書きます。とりあえずこう書けばOK

    本来はもうちょっとPHP Extensionらしい書き方が有るんですが長くなるので今回はこんな形でごまかしちゃいましょう。

    続いてPHPにExtensionを登録するためのコードを書きます。

  • php_migemo.h
  • #ifndef PHP_MIGEMO_H
    #define PHP_MIGEMO_H
    
    #define PHP_MIGEMO_EXTNAME "migemo"
    #define PHP_MIGEMO_EXTVER "0.1"
    
    
    #ifdef HAVE_CONFIG_H
    #include "config.h"
    #endif
    
    #include "php.h"
    #include 
    
    extern zend_module_entry migemo_module_entry;
    #define phpext_migemo_ptr &migemo_module_entry;
    
    PHPAPI zend_class_entry *migemo_class_entry;
    
    #endif /* PHP_MIGEMO_H */
    
  • migemo.c
  • #include "php_migemo.h"
    
    PHPAPI function_entry php_migemo_methods[] = {
        {NULL, NULL, NULL}
    };
    
    PHP_MINIT_FUNCTION(migemo) {
        return SUCCESS;
    }
    
    PHP_MINFO_FUNCTION(migemo)
    {
        return SUCCESS;
    }
    
    zend_module_entry migemo_module_entry = {
    #if ZEND_MODULE_API_NO >= 20010901
        STANDARD_MODULE_HEADER,
    #endif
        PHP_MIGEMO_EXTNAME,
        NULL, 					/* Functions */
        PHP_MINIT(migemo),	    /* MINIT */
        NULL, 	                /* MSHUTDOWN */
        NULL, 	                /* RINIT */
        NULL,	                /* RSHUTDOWN */
        PHP_MINFO(migemo),	    /* MINFO */
    #if ZEND_MODULE_API_NO >= 20010901
        PHP_MIGEMO_EXTVER,
    #endif
        STANDARD_MODULE_PROPERTIES
    };
    
    #ifdef COMPILE_DL_MIGEMO
    ZEND_GET_MODULE(migemo)
    #endif
    

    そいでは準備ができましたのでコンパイルしてみましょう。

    phpize
    ./confiugre
    make
    sudo make install
    
    # migemo本体の共有ライブラリいれてからldconfigしてなかったので初回だけ。
    sudo ldconfig
    

    php5のconfファイルにmigemo.soを追加します。

  • /etc/php5/conf.d/migemo
  • extension=migemo.so

    これでPHPにMigemo Extensionを登録するだけのExtensionが作れました。

    chobie@air:~/src/php-migemo$ php -m | grep migemo
    migemo
    

    確かにPHPExtensionがロードされているようですね。UnitTestも実行しておきましょう。

    chobie@air:~/src/php-migemo$ phpunit MigemoTest.php 
    PHPUnit 3.5.6 by Sebastian Bergmann.
    
    .FSSS
    
    Time: 0 seconds, Memory: 3.00Mb
    
    There was 1 failure:
    
    1) MigemoTest::testMigemoClassExists
    Failed asserting that  matches expected .
    
    /home/chobie/src/php-migemo/MigemoTest.php:19
    
    FAILURES!
    Tests: 2, Assertions: 2, Failures: 1, Skipped: 3.
    

    きちんとモジュールが読み込まれるテストは成功していますね。

    クラスだけを実装する

    それではMigemoクラスをExtensionで実装してみましょう。まずは単純にクラスの定義だけを行ないます。PHPで言えばこんなコードになります。

    <?php
    class Migemo{}
    

    新しいクラスを定義するにははPHP_MINIT_FUNCTION(migemo)に3行追加するだけで出来ます。

  • migemo.c
  • PHP_MINIT_FUNCTION(migemo) {
        zend_class_entry ce;
        INIT_CLASS_ENTRY(ce, "Migemo", php_migemo_methods);
        migemo_class_entry = zend_register_internal_class(&ce TSRMLS_CC);
        return SUCCESS;
    }
    

    コレだけです。zend_class_entry `migemo_class_entry`は前もってphp_migemo.h で宣言しておいたのでPHP_MINIT_FUNCTIONで使うことができます。

    INIT_CLASS_ENTRYは一番目にzend_class_entry、2番目にクラス名、3番目にクラスに 対応したfunction_entryを渡せばOKです。

    それでは再度コンパイルしてチェックしてみましょう。

    sudo make install
    
    chobie@air:~/src/php-migemo$ phpunit MigemoTest.php 
    PHPUnit 3.5.6 by Sebastian Bergmann.
    
    ..FII
    
    Time: 0 seconds, Memory: 3.00Mb
    
    There was 1 failure:
    
    1) MigemoTest::testQueryMethodExists
    Failed asserting that  matches expected .
    
    /home/chobie/src/php-migemo/MigemoTest.php:28
    
    FAILURES!
    Tests: 5, Assertions: 3, Failures: 1, Incomplete: 2.
    

    2つテストが成功しました。クラスも定義できたのでどんどん進みましょう。

    queryメソッドを実装してみる

    ひとまずこれでMigemoクラスが扱えるようになったので地味な部分はとりあえずおいておいてqueryメソッドを実装してしまいましょう。

    メソッドの追加は先程`INIT_CLASS_ENTRY`で指定した`php_migemo_methods`に どんなメソッドがあるかを追加しておけばOKです。

    PHPAPI function_entry php_migemo_methods[] = {
        PHP_ME(migemo, query, arginfo_migemo_query, ZEND_ACC_PUBLIC)
        {NULL, NULL, NULL}
    };
    

    function_entry配列のお約束は最後は必ず{NULL,NULL,NULL}で締める、という事を守っておけばOK。PHP_MEなどのfunction_entry用マクロのあとは ,は必要ありません。大体一緒なので雰囲気で書いちゃいましょう。

    これでMigemoクラスにはqueryというメソッドがあるよ!というのを定義出来ました。 肝心の実装はどう書くかというと。

    ZEND_BEGIN_ARG_INFO_EX(arginfo_migemo_query, 0, 0, 1)
        ZEND_ARG_INFO(0, query)
    ZEND_END_ARG_INFO()
    PHP_METHOD(migemo, query)
    {
        migemo *m;
        char *query;
        int ret = 0;
        int query_len = 0;
        unsigned char *result;
        if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC,
            "s", &query, &query_len) == FAILURE){
            return;
        }
    
        m =  migemo_open("/usr/local/share/migemo/utf-8/migemo-dict");
        result = migemo_query(m, query);
    
        RETVAL_STRING(result, 1);
        migemo_release(m, result);
        migemo_close(m);
    }
    

    こんな感じです。Zend Engine2周りの関数やマクロが入ってきて若干分かりづらいかもしれませんがこれはこういうもんだと思っておけば大丈夫です。

    RETVAL_STRINGはZEND_APIで定義されているマクロの一つでメソッドや関数の返り値を 簡単に設定できるマクロです。RETVAL系のマクロを使うとCの型からPHPの型に簡単に 変換しつつ返り値の設定をしてくれるので便利ですね。

    それではまたコンパイルして試してみましょう

    sudo make install
    
    chobie@air:~/src/php-migemo$ phpunit MigemoTest.php 
    PHPUnit 3.5.6 by Sebastian Bergmann.
    
    .....
    
    Time: 7 seconds, Memory: 3.00Mb
    
    OK (5 tests, 34 assertions)
    

    おー、ちゃんと動いていますね!

    しかし今のままだとqueryメソッドを呼ぶ際に毎回migemoの初期化と解放をしているのが気に入りません。

    それではコンストラクタを実装してみましょう。

    コンストラクタを実装

    コンストラクタの実装と行きたいのですがよく考えてみると一つ困ったことがでてきました。 migemoポインタはどこに格納しておけばよいのでしょう?

    クラスのインスタンス関連付けて何かしらの構造を持ち回したい場合は自前の 構造体を定義してクラス生成時のオブジェクトの生成をハンドリングする方法を使います。

    オブジェクトの生成をハンドリングする為にはオブジェクトを作るための関数と、オブジェクトが作ったメモリを開放するための関数を定義してzend_class_entry->create_object にオブジェクトを作成する為の関数を設定してあげます。

  • migemo.c
  • typedef struct{
        zend_object zo;
        migemo *migemo;
    } php_migemo;
    

    構造体のキャストを行なっているので先頭はzend_objectでなければいけません。

    続いてオブジェクトの生成と解放を行う関数を追加します。殆ど同じなのでこういうもんだと思ってコピペすればOKです。大事なところは緑でマーキングしておいたので自分で違うのを作る場合は参考にしてください。

  • migemo.c
  • static void php_migemo_free_storage(php_migemo *object TSRMLS_DC)
    {
        zend_object_std_dtor(&object->zo TSRMLS_CC);
        
        if(!object->migemo){
          migemo_free(object->migemo);
        }
        object->migemo = NULL;
        efree(object);
    }
    
    zend_object_value php_migemo_new(zend_class_entry *ce TSRMLS_DC)
    {
    	zend_object_value retval;
    	php_migemo *obj;
    	zval *tmp;
    
    	obj = ecalloc(1, sizeof(*obj));
    	zend_object_std_init( &obj->zo, ce TSRMLS_CC );
    	zend_hash_copy(obj->zo.properties, &ce->default_properties, (copy_ctor_func_t) zval_add_ref, (void *) &tmp, sizeof(zval *));
    
    	retval.handle = zend_objects_store_put(obj, 
            (zend_objects_store_dtor_t)zend_objects_destroy_object,
            (zend_objects_free_object_storage_t)php_migemo_free_storage,
            NULL TSRMLS_CC);
    	retval.handlers = zend_get_std_object_handlers();
    	return retval;
    }
    

    コンストラクタを追加します。

    PHP_METHOD(migemo, __construct){
        php_migemo *this = (php_migemo *) zend_object_store_get_object(getThis() TSRMLS_CC);
    
        this->migemo = migemo_open("/usr/local/share/migemo/utf-8/migemo-dict");
    }
    

    コンストラクタを追加したのでメソッド定義とクラスの初期化部分に少し手を入れます。

    PHPAPI function_entry php_migemo_methods[] = {
        PHP_ME(migemo, __construct, NULL, ZEND_ACC_PUBLIC)
        PHP_ME(migemo, query, arginfo_migemo_query, ZEND_ACC_PUBLIC)
        {NULL, NULL, NULL}
    };
    
    PHP_MINIT_FUNCTION(migemo) {
        zend_class_entry ce;
        INIT_CLASS_ENTRY(ce, "Migemo", php_migemo_methods);
        migemo_class_entry = zend_register_internal_class(&ce TSRMLS_CC);
    migemo_class_entry->create_object = php_migemo_new;
    
        return SUCCESS;
    }
    

    コンストラクタ側でmigemoの生成行うようにしたので、それに合わせて queryの実装を変更します。

    PHP_METHOD(migemo, query)
    {
        php_migemo *this = (php_migemo *) zend_object_store_get_object(getThis() TSRMLS_CC);
        char *query;
        int ret = 0;
        int query_len = 0;
        unsigned char *result;
        if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC,
            "s", &query, &query_len) == FAILURE){
            return;
        }
    
        result = migemo_query(this->migemo, query);
    
        RETVAL_STRING(result, 1);
        migemo_release(this->migemo, result);
    }
    

    これで実装が完了しましたね。もう一回コンパイルして試してみましょう。

    chobie@air:~/src/php-migemo$ phpunit MigemoTest.php 
    PHPUnit 3.5.6 by Sebastian Bergmann.
    
    .....
    
    Time: 0 seconds, Memory: 3.00Mb
    
    OK (5 tests, 34 assertions)
    

    ユニットテストの時間が短縮されていて効果が出ていますね。これで実装が終了しました!

    あとがき

    どうでしたか?思っていたより簡単に開発できたのではないでしょうか?

    PHPバインディングから始めるExtension作成は割と身近で親しみやすく、 次に自分が何を調べるべきかという目標が明確に分かるのでとっかかりには オススメだと思います。

    最後に参考になるリンクと宣伝を貼っておきます。

  • php-migemo http://github.com/chobie/php-migemo
  • 今回作成したExtensionのGitリポジトリです。

  • php-git http://github.com/chobie/php-git
  • php-gitはlibgit2をPHPで扱えるようにする為のPHPバインディングです。最近作り始めたばかりなので まだまだalpha developmentで課題はたくさん有りますがPHPでgit repositoryを使った操作が行えます。

  • ZendEngine 勉強会グループ http://groups.google.com/group/php-zendengine/
  • 2011年2月か3月に東京でZendEngineについての勉強会を行ないます。私もLT予定ですので ご興味のある方はぜひぜひどうぞ!

  • [klabさん] PHP Extension を作ろう第1回 - まずは Hello World
  • [klabさん] PHP Extension を作ろう第2回 - 引数と返値
  • [klabさん] PHP Extension を作ろう第3回 - クラスを作ろう
  • [yoyaさん] PHP extension の作り方
  • [rskyさん] 実例で学ぶPHP拡張モジュールの作り方 第6回 PHP 5.3の変更点(その2)
  • それでは、みんなも作ってア・ラ・モード☆

    Zynga Japanでは積極的にエンジニアを採用しています。
    採用ページをご覧になり、興味のある方はぜひご応募ください。

    2011年1月 7日

    flashlite1.1で文字圧縮してみた
    このエントリーをはてなブックマークに追加 このエントリーをlivedoorクリップに追加

    明けましておめでとうございます&はじめまして。12月に入社した加藤です。

    FlashLite 2.0をやるつもりで入ってみたらバリバリ1.1だったので、出す機会を逸していたネタをここで出したいと思います。

    FlashLite 1.1の制限にはいろいろありますが、開発する上で一番困るのは100KB制限です。
    100KBと言うと、このページの右カラムに並んでいる著者一覧の写真が一つだいたい8KBくらいですので、だいたい12枚分になります。その中にグラフィックとスクリプト両方をつめ込まねばなりません。
    普通のFLASHならパブリッシュ設定の「ムービーの圧縮」にチェックを入れれば圧縮が有効になるのですが、残念ながらFlashLite 1.1ではその機能はグレーアウトされて使えません。
    そういうわけでFlashLite 1.1のエンジニアは日々シェイプの最適化から変数名の文字数まで、地道な作業に血道をあげています。

    しかし、生成エンジンで変数差し込みをする場合、いくらswfを最適化したところで「100KB-swfのファイルサイズ」分のデータしか入れられません。Twitterクライアントを作っていたとき、これだと50件表示までしか出来なくて何とかして100件表示にしたいと思い辿り着いたのが文字圧縮です。

    圧縮というとzipやらrarやらといったでお馴染みのアレですが、通常の圧縮形式は圧縮率を稼ぐために符号化やらなにやら様々な処理を行っていて、圧縮率が高い代わりに圧縮/展開処理が複雑で実行にも時間がかかります。いろんな意味で非力なFlashLite1.1では実装も難しい上、圧縮は疎か展開するにも非常に時間がかかってしまい、現実的ではありません(と言いつつ一人ハフマン符号化して圧縮を実装した人を知っていますが)。そこで目をつけたのはBPEという方法です。

    BPEとはByte Pair Encodingの略で、「隣り合った二文字を使われていない一文字で置き換える」という圧縮方法です。例えば、「ABCDABCDABCDABCDABCD」という文字列をBPEで圧縮すると、ABを使われていないXに、CDをYに置き換え、「XYXYXYXYXY」となります。あとはX=AB、Y=CDという置換対応表を別で持っておけば、「XYXYXYXYXY」を「ABCDABCDABCDABCDABCD」に文字列置換だけで戻すことができます。とても単純です。ただし、その替りに圧縮率が悪く、このままではどうやっても50%以下には縮みません。しかし、その単純さ故に殆どCPUパワーを食わないため、とてもFlashLite向きと言えます(圧縮処理は重いという特徴もあるのですが、変数差し込みに使う場合それはサーバ側で行えばよく、問題になりません)。

    では実際の文章で試してみましょう。まずは圧縮からです。今回は「吾輩は猫である」を使います。
    英文を圧縮する場合は隣り合った2文字を1文字で置き換えますが、この場合は文章が日本語なので、2バイト文字を使われていない1バイト文字で置き換えます。頻出度合いが低くなると圧縮効果が落ちますので、今回は頻出上位60文字を抽出し置き換えました。方法は割愛。

    元の文章

     吾輩は猫である。名前はまだ無い。
     どこで生れたかとんと見当がつかぬ。何でも薄暗いじめじめした所でニャ―ニャ―泣いていた事だけは記憶している。吾輩はここで始めて人間というものを見た。しかもあとで聞くとそれは書生という人間中で一番獰悪な種族であったそうだ。この書生というのは時々我々を捕えて煮て食うという話である。しかしその当時は何という考もなかったから別段恐しいとも思わなかった。ただ彼の掌に載せられてス―と持ち上げられた時何だかフワフワした感じがあったばかりである。掌の上で少し落ちついて書生の顔を見たのがいわゆる人間というものの見始であろう。この時妙なものだと思った感じが今でも残っている。第一毛をもって装飾されべきはずの顔がつるつるしてまるで薬缶だ。その後猫にもだいぶ逢ったがこんな片輪には一度も出会わした事がない。のみならず顔の真中があまりに突起している。そうしてその穴の中から時々ぷうぷうと煙を吹く。どうも咽せぽくて実に弱った。これが人間の飲む煙草というものである事はようやくこの頃知った。

    BPE圧縮後

     RN-O&/*。名前-E1無"。
     _0&?4#,$]$:[.<,ぬ。H&'薄暗">I>I)#所&ZYKZYK泣"("#A1け-記憶)("*。RN-00&`I(;9$"%'!8:#。),'/$&聞@$34-B?$"%;9D&C番獰悪2種族&/+#3%1。0!B?$"%!-6F我F8捕え(煮(食%$"%話&/*。),)3![6-H$"%考'2,+#,7別段恐)"$'PG2,+#。#1彼!Q5載T74(スK$持VSげ74#6H1,X^X^)#W>./+#ば,\&/*。Q!S&少)落V<"(B?!J8:#!."Gゆ*;9$"%'!!:`&/ろ%。0!6妙2'!1$P+#W>.今&'残+("*。第C毛8'+(装飾さ4べき-U!J.<*<*)(E*&薬缶1。3!後O5'1"ぶ逢+#.0]2片輪5-C度'出会G)#A.2"。!み27UJ!真D./E\5突起)("*。3%)(3!穴!D,76FL%L%$M8吹@。_%'咽Tぽ@(実5弱+#。04.;9!飲むM草$"%'!&/*A-よ%や@0!頃知+#。

    文字数は双方450文字と変わりませんが、サイズは元が896バイトに対し、圧縮後は539バイトになりました。約60%に圧縮されたということになります。この時、置換対応表は以下のようになります。

    !=の
    "=い
    #=た
    $=と
    %=う
    &=で
    '=も
    (=て
    )=し
    *=る
    +=っ
    ,=か
    -=は
    .=が
    /=あ
    0=こ
    1=だ
    2=な
    3=そ
    4=れ
    5=に
    6=時
    7=ら
    8=を
    9=間
    :=見
    ;=人
    <=つ
    >=じ
    ?=生
    @=く
    A=事
    B=書
    C=一
    D=中
    E=ま
    F=々
    G=わ
    H=何
    I=め
    J=顔
    K=ー
    L=ぷ
    M=煙
    N=輩
    O=猫
    P=思
    Q=掌
    R=吾
    S=上
    T=せ
    U=ず
    V=ち
    W=感
    X=フ
    Y=ャ
    Z=ニ
    [=当
    \=り
    ]=ん
    ^=ワ
    _=ど
    `=始

    あとはこれを元に展開すればいいわけです。FlashLite1.1には置換系のメソッドがないので少々面倒ですが、僕は以下のように実装しました。

    1フレーム目
    stop();
    
    //デコードキー
    keys = "!\"#$%&'()*+,-./0123456789:;<>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`";
    //デコード文字列
    vals = "のいたとうでもてしるっかはがあこだなそれに時らを間見人つじ生く事書一中ま々わ何め顔ーぷ煙輩猫思掌吾上せずち感フャニ当りんワど始";
    //圧縮後文字列
    bpe_text = " RN-O&/*。名前-E1無\"。\n _0&?4#,$]$:[.<,ぬ。H&'薄暗\">I>I)#所&ZYKZYK泣\"(\"#A1け-記憶)(\"*。RN-00&`I(;9$\"%'!8:#。),'/$&聞@$34-B?$\"%;9D&C番獰悪2種族&/+#3%1。0!B?$\"%!-6F我F8捕え(煮(食%$\"%話&/*。),)3![6-H$\"%考'2,+#,7別段恐)\"$'PG2,+#。#1彼!Q5載T74(スK$持VSげ74#6H1,X^X^)#W>./+#ば,\&/*。Q!S&少)落V<\"(B?!J8:#!.\"Gゆ*;9$\"%'!!:`&/ろ%。0!6妙2'!1$P+#W>.今&'残+(\"*。第C毛8'+(装飾さ4べき-U!J.<*<*)(E*&薬缶1。3!後O5'1\"ぶ逢+#.0]2片輪5-C度'出会G)#A.2\"。!み27UJ!真D./E\\5突起)(\"*。3%)(3!穴!D,76FL%L%$M8吹@。_%'咽Tぽ@(実5弱+#。04.;9!飲むM草$\"%'!&/*A-よ%や@0!頃知+#。";
    
    // キーの数を取得
    key_count = length(keys);
    
    // 繰り返し使うので連番変数にしてしまう。rkが半角文字、rcは全角文字。
    for (i=1; i<=key_count; i++) {
    	set("rk" add i, substring(keys, i, 1));
    	set("rc" add i, mbsubstring(vals, i, 1));
    }
    
    // BPEをデコード
    text_length = mblength(bpe_text);
    decoded_text = "";
    for (j=1; j<=text_length; j++) {
    	// 一文字ずつ変数cに格納
    	c = mbsubstring(bpe_text, j, 1);
    	call("DECODE");
    	decoded_text = decoded_text add c;
    }
    // 元の文章が出力される筈
    trace(decoded_text);
    
    2フレーム目
    // フレームラベル「DECODE」とつける
    for (m=1; m<=key_count; m++) {
        if (get("rk" add m) eq c) {
            set("c", get("rc" add m));
            break;
        }
    }
    

    一文字ずつ走査してcに文字を代入し、DECODEフレームでキーと合う文字列があったら置き換える、といった方法で圧縮された文字列を展開して元の文章に戻しています。
    上ではデコードキーとデコード文字列を連結して渡し、flash内で1文字ずつ変数化していますが、もちろん変数化した後の値を渡しても構いません。
    経験則では日本語の文章はだいたい70%以下にまで縮みますので、50KBの所に70KB程の文字列が入る事になります。これはTwitterの発言に換算しますと、1発言が最大140文字で全てが2バイト文字の場合は140*2で280バイトになりますので、ざっと50発言程多く入れられる計算です。

    圧縮は兎も角展開については割と簡単な実装で実現できますので、文字列が多く差し込まれるswfで容量が厳しいときは検討してみてはいかがでしょうか?

    Zynga Japanでは積極的にエンジニアを採用しています。
    採用ページをご覧になり、興味のある方はぜひご応募ください。

    2011年1月 6日

    入社後なるべく早くキャッチアップするために心がけたこと
    このエントリーをはてなブックマークに追加 このエントリーをlivedoorクリップに追加

    あけましておめでとうございます。
    chunoです。

    弊社には(身内自慢になるかもしれませんが)手練のエンジニアが老若男女問わず揃っており、ギークでもスーパープログラマでもない私にとっては

    「一番の下手くそ」

    でいられる、成長するためには理想的な環境です。

    ※参考「情熱プログラマー」第一章の4


    とは言え、そういう状況で安穏としているわけにもいかないので、少しでも早く周囲にキャッチアップできるよう努めました。

    それらについて、これから述べます。


    ■周りの人の助力を仰ぐ

     入社直後にアサインされたプロジェクトが佳境を迎えていたことに加え、個人的な経験やスキルは以下のような状況でした。

    • symfony→使ったこと無し
    • TDD(テスト駆動開発)→未経験
    • memcached→使ったこと無し
    • Git→使ったこと無し

     結構テンパっていたのですが、良き先輩であるチームメンバーに積極的に教えを乞いました。
     質問する際は、ノートに図を書いたりして持って行くと、こちらの「聞きたいこと、理解できていないこと」が伝わりやすくなります。
    ※無闇矢鱈と質問しに行ってお仕事の邪魔をしたことがあります、ゴメンナサイ...


    ■ペアプログラミングの提案

     TDDに不慣れだったり、自分の開発手法に不安があったりする場合は、ペアプログラミングをお願いするのも手です。
    開発方法が学べたり、コードの質も向上します。
     ただし、ものすごく疲れるので、細目に休憩は取ってください。
    ※喫煙者の方と組むと「そろそろタバコ休憩しますか」という提案をしやすいのでオススメです(半分冗談です...)。


    ■意見することを恐れない

     マンツーマンの面談だとそうでもないでしょうが、大勢で参加しているミーティング等で自分の意見を述べるのは、多少の勇気を必要とします。
     ですが、意見を持てるということは、それだけ物事を真剣に考えている証拠でもあるので、思うところがあるのなら是非とも自信を持って口に出すべきです。
     (もちろん、発言の仕方には十分な配慮が必要ですが...)
     なお、意見することで自分が感じたメリットには以下のようなものがあります。

    • 皆にとって良い意見であれば採り入れてもらえます
    • 自分の考え方と異なる意見を聞く機会ができます
    • 自分の発言がキッカケで新たな建設的な議論が始まる可能性もあります

    ■指摘を受けたら素直に受け入れる

     ミスを犯した際はもちろん、各種ミーティングや、設計レビュー、ペアプログラミング等で耳の痛いことを言われても、自分が成長するためのキッカケだと考えて素直に受け入れました。
     また、これらをノートやWiki、ブログ等に書き留めておくと、同じ失敗を繰り返す確率が減りますし、自分だけの財産にもなります。


    ■自動化できるところは自動化する

     私はVimで開発を行っていますが、ケアレスミス防止のために、以下のようなスクリプトを「.vimrc」に書きました。
    ファイル書き込み時に自動でPHPの構文チェックをしてくれます。
    (同様なものは既に色々な方々がネット上で公開されていますが...)
    autocmd BufWritePost *.php :call PHPLint()
    function PHPLint() let result = system( &ft . ' -l ' . bufname(""))
    let headPart = strpart(result, 0, 16)
    if headPart != "No syntax errors"
    echo result
    endif
    endfunction


    ■できないことはできないと言う

     どうしても遠慮がちになったり、「期待に応えないと!」という気持ちが強くなったりで、なかなか「No」と言いづらいものですが、スケジュール的なことだったり、その他諸々について無理だと思ったら、正直に伝えたほうが良いです。
    それで相手の心象を悪くすることはありませんし、 
    「では○○だったら可能ですか」 
    「△△だったら可能です」 
    といった歩み寄りのやり取りで、双方にとって好ましい結果に落ち着かせることができます。 
    ※「俺ヤル気ねーよ、やりたくねーよ」みたいな態度は論外ですが。


    ■見ている人は見ている

     良い意味でも悪い意味でも、見られているものです(普段の立ち居振る舞いだったり、SVNのコミットログだったり...)。
    特に入社したばかりの人は目につきやすいので、勤務態度等には気をつけましょう。
     そして、淡々と実直にお仕事をしていれば、徐々に周囲の人達も認めてくれるようになり、飲みの席でも一層話が弾むようになります。
    そうなるまである程度時間はかかりますが、焦らないことが肝要です。
    ※myChuno.class.phpとかmyChuno◯◯ってデータの入ったyamlをコミットしてしまってゴメンナサイ...


    ■勉強会やセミナーに参加する

     都合がつけば、ドシドシ参加してみましょう。
    (私は、PHPカンファレンス2010や、弊社で行われた第一回Symfony2勉強会に参加しました)
    他社様の開発事例を耳にしたり、会社の同僚や先輩が発表する様子を目にしたり、自社以外で活躍されているエンジニアの方々と出会うことで、自分に足りないものを認識したり、自分が自信を持てるものを見つけたり...と、得られるものは多々あります。
    ※なお、第二回Symfony2勉強会も弊社で開催します!


    以上です。

    新しい環境下で不安な気持ちを持たれている方の一助となれば幸いです。

    そして...
    Zynga Japanでは積極的にエンジニアを採用しています。
    採用ページをご覧になり、興味のある方はぜひご応募ください。

    もし、本ブログをご覧いただいた方々と一緒に働くことができたら、最高です!

    2011年1月 5日

    Valgrindを使って楽々PHP拡張モジュール開発のデバッグ
    このエントリーをはてなブックマークに追加 このエントリーをlivedoorクリップに追加

    明けましておめでとうございます。@emorinsです。

    みなさんモジュール開発ではどのようにデバッギングしていますか?モジュールになると普段使い慣れたデバッグツールが使えず、手動の動作確認だけで済まされている方もいらっしゃるのではないでしょうか。

    今回はC/C++開発ではメジャーなメモリデバッガ『Valgrind』をPHP拡張モジュールの開発で活用することで、普段使い慣れたツールでのデバッグの例をご紹介します。

    1.PHP拡張モジュールの作成

    まず開発用にPHPをデバッグモードでビルド。

    #cd ./php-5.x.x
    #./configure --enable-debug
    #make
    #make install

    PHP拡張モジュールを作成

    #cd ./ext
    #./ext_skel --extname=zynga_func
    #cd zynga_func

    16行目から18行目のコメントアウトを外す

    #emacs config.m
    - dnl PHP_ARG_ENABLE(zynga_func, whether to enable zynga_func support,
    - dnl Make sure that the comment is aligned:
    - dnl [  --enable-zynga_func           Enable zynga_func support])
    + PHP_ARG_ENABLE(zynga_func, whether to enable zynga_func support,
    + Make sure that the comment is aligned:
    + [  --enable-zynga_func           Enable zynga_func support])

    拡張モジュールのビルド

    #phpize
    #./configure
    #make
    #make install

    php.iniに以下を追加

    extension=zynga_func.so

    同一ディレクトリ内に生成されているテスト用PHPコードを実行

    #php zynga_func.php

    以下のように出力されたらモジュールの正常な読み込みに成功。

    Functions available in the test extension:
    confirm_zynga_func_compiled
    
    

    Congratulations! You have successfully modified ext/zynga_func/config.m4.
    Module zynga_func is now compiled into PHP.

    これで正常にPHP拡張モジュールの生成と読み込みが確認できたので、Valgrindでデバッギングしてみましょう。

    2.Valgrindによるデバッグ

    Valgrindにはいくつかのツールが付属したツール群になっていますが、まず最も使用するであろうMemcheckによるメモリーリーク、初期化・開放などのメモリ周りのデバッグログを出力してみましょう。

    #valgrind php zynga_func.php
    ==2107==
    ==2107== HEAP SUMMARY:
    ==2107==     in use at exit: 104,669 bytes in 9 blocks
    ==2107==   total heap usage: 10,973 allocs, 10,964 frees, 2,127,924 bytes  allocated
    ==2107==
    ==2107== LEAK SUMMARY:
    ==2107==    definitely lost: 0 bytes in 0 blocks
    ==2107==    indirectly lost: 0 bytes in 0 blocks
    ==2107==      possibly lost: 0 bytes in 0 blocks
    ==2107==    still reachable: 104,669 bytes in 9 blocks
    ==2107==         suppressed: 0 bytes in 0 blocks
    ==2107== Rerun with --leak-check=full to see details of leaked memory
    ==2107== 
    ==2107== For counts of detected and suppressed errors, rerun with: -v
    ==2107== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)

    ※ログの見方

    • HEAP SUMMARY: どれだけのヒープ領域を使用し、解放したかの数値。
    • LEAK SUMMARY: メモリーリークが起きているbyte数とblock数。
    • ERROR SUMMARY: エラー数

    ログから、メモリーリークは一切起きておらず、ヒープ領域も僅かに開放されていない箇所もあるが、正常に動作していると言えます。

    次にわざとメモリーリークを起こすコードを関数内に埋め込んでみます。zynga_func.c内の、PHP_FUNCTION(confirm_zynga_func_compiled)関数が、先ほどzynga_func.phpで実行された関数になるので、その中の処理を書き換えます。

    mallocで確保しているにも関わらずfreeで開放していないため、メモリーリークが起きるコード。

    #emacs zynga_func.c
    void f(void)
    {
        int* x = malloc(10 * sizeof(int));
        x[10] = 0;        // problem 1: heap block overrun
    }                    // problem 2: memory leak -- x not freed
    PHP_FUNCTION(confirm_zynga_func_compiled)
    {
        f();
        ....

    ビルドして反映。

    #make
    #make install

    valgrindで確認。

    #valgrind php zynga_func.php
    ==4934== Invalid write of size 4
    ==4934==    at 0x101231C14: f (in /usr/local/lib/php/extensions/debug-non-zts-20060613/zynga_func.so)
    ==4934==    by 0x101231C3B: zif_confirm_zynga_func_compiled (in /usr/local/lib/php/extensions/debug-non-zts-20060613/zynga_func.so)
    ==4934==    by 0x100308AF3: zend_do_fcall_common_helper_SPEC (in /usr/local/bin/php)
    ==4934==    by 0x100309A06: ZEND_DO_FCALL_BY_NAME_SPEC_HANDLER (in /usr/local/bin/php)
    ==4934==    by 0x1003084FB: execute (in /usr/local/bin/php)
    ==4934==    by 0x1002DD728: zend_execute_scripts (in /usr/local/bin/php)
    ==4934==    by 0x100279F64: php_execute_script (in /usr/local/bin/php)
    ==4934==    by 0x10036A507: main (in /usr/local/bin/php)
    ==4934==  Address 0x1010b1298 is 0 bytes after a block of size 40 alloc'd
    ==4934==    at 0x10062D79F: malloc (vg_replace_malloc.c:236)
    ==4934==    by 0x101231C07: f (in /usr/local/lib/php/extensions/debug-non-zts-20060613/zynga_func.so)
    ==4934==    by 0x101231C3B: zif_confirm_zynga_func_compiled (in /usr/local/lib/php/extensions/debug-non-zts-20060613/zynga_func.so)
    ==4934==    by 0x100308AF3: zend_do_fcall_common_helper_SPEC (in /usr/local/bin/php)
    ==4934==    by 0x100309A06: ZEND_DO_FCALL_BY_NAME_SPEC_HANDLER (in /usr/local/bin/php)
    ==4934==    by 0x1003084FB: execute (in /usr/local/bin/php)
    ==4934==    by 0x1002DD728: zend_execute_scripts (in /usr/local/bin/php)
    ==4934==    by 0x100279F64: php_execute_script (in /usr/local/bin/php)
    ==4934==    by 0x10036A507: main (in /usr/local/bin/php)
    ==4934==    Congratulations! You have successfully modified ext/zynga_func/config.m4. Module zynga_func is now compiled into PHP.
    ==4934== 
    ==4934== HEAP SUMMARY:
    ==4934==     in use at exit: 104,709 bytes in 10 blocks
    ==4934==   total heap usage: 10,974 allocs, 10,964 frees, 2,127,964 bytes allocated
    ==4934== 
    ==4934== LEAK SUMMARY:
    ==4934==    definitely lost: 40 bytes in 1 blocks
    ==4934==    indirectly lost: 0 bytes in 0 blocks
    ==4934==      possibly lost: 0 bytes in 0 blocks
    ==4934==    still reachable: 104,669 bytes in 9 blocks
    ==4934==         suppressed: 0 bytes in 0 blocks
    ==4934== Rerun with --leak-check=full to see details of leaked memory

    今度はリークしている箇所と、byte数・block数がログに出力されるのを確認できました。

    Valgrindはメモリーリークの検出以外に、初期化されていないメモリ領域の使用、freeされたメモリ領域の使用、ヒーププロファイラ、キャッシュプロファイラなど多用の機能を備えています。

    普段使い慣れたツールで、開発に負荷のかからないデバッグを行っていきましょう。


    Zynga Japanでは積極的にエンジニアを採用しています。

    採用ページをご覧になり、興味のある方はぜひご応募ください。

    アジャイル開発におけるテストについて(その1)
    このエントリーをはてなブックマークに追加 このエントリーをlivedoorクリップに追加

    初めまして、11月に入社したQA担当のものです。

    短期間の開発はどうしても少ない工数でテストを実行したい...と、だんだん重要になってくる。その中でアジャイルテスティングが最も有効で、尚且つ効率で不具合を発見できる方法と思います。

    アジャイルテストは反復 (イテレーション) と呼ばれる短い期間単位を採用することで、リスクを最小化しようとしている。アジャイルテストは4象限の分類で説明されている。

    概要は以下のとおり。


    1. 第1象限はチームを支援する技術面のテスト
      → テスト駆動開発などアジャイル開発の中心

    2. 第2象限はチームを支援するビジネス面のテスト
      → 顧客の視点からのハイレベルの機能テストなど

    3. 第3象限は製品を批評するビジネス面のテスト
      → ユーザー受入テスト、探索的テストなど

    4. 第4象限は技術面のテストを使った製品の批評
      → パフォーマンステスト、セキュリティテストなど

    この4現象に分けて、テストチームとアプリケーションにあわせテストを行っていく。

    こちらの4象限をテスト対象物にあわせ、決められた期間で有効にアジャイルプロセスを実行するために、可能な限りプランニングし、スケジューリング・要件定義・観点・テスト種類/技法・テストツールを決める。また、長期間ならWork Breakdown Structure(WBS)がプロセスと進捗管理の全体を細かく作業に分割し、管理するのが理想だが、短期間の場合はテストの観点とテスト技法に重点を置くこと。

    テスト作業については以下のように含まれる。

    • テスト観点の網羅
    • テストアプリケーションの定義
    • テスト種類や技法の選択
    • テストツールの選択
    • インシデントレポート
    • リグレッションテスト(回帰テスト)

    このような手法で繰り返すテストすることでより堅牢かつ高品質のアプリケーションを目指せると思う。初めての記載だが皆さんに参考できると願います。もちろんテスト担当者はそれぞれのやり方があるので、ご意見・ご指摘をぜひお願いします。

    次回は更にアジャイルテストとは別でこれからも注視したいテスト方法を紹介する予定。ご期待ください。