技術ブログ - 毎日が成長!

2009年5月 のアーカイブ

新オフィス候補の内覧

2009年5月22日 金曜日

そろそろ創業10年目ということで、オフィスがだいぶ手狭になってきたサーバーワークスです。すでにデスクを増やすのも限界になりつつあるのですが、それよりも開発メンバー的には「足を伸ばしてゴロゴロできる畳」が欲しい今日この頃。

本日は午前中を使って新しいオフィス候補物件の内覧を行いました。さいわい候補物件はいずれも現オフィスから歩いて数分の立地なので、総勢約20名でゾロゾロと江戸川橋を練り歩いて参りました。

20090522-new-office

スタッフの意識は物件そのものよりも、間取りはどうなる、内装はどうする、喫煙スペースはあるのか、床は簡単にめくれるか、トイレの数は充分か、畳!といったところ注がれていたような気がします。やっぱり、物件選びはテンションがあがりますね。

引っ越しまであと半年、どんなオフィスになるのでしょうか。

Leopardでコマンドラインからアカウントを追加する

2009年5月20日 水曜日

sshでリモートログインしたMac OS X Leopard上でアカウント追加を行い、sudoでそのアカウントになれるようにする必要があったので調べてみたところ、dscl(Directory Service command line utility)というコマンドで行えることがわかりました。

以前はNetInfo(NetInfo Manager)でゴニョゴニョやったものですが、LeopardからはバックエンドがdsLocalというデータベースに変わったので、このあたりの勝手も変わっているようです。

アカウントの一覧

$ dscl . -list /Users

アカウントの追加

$ sudo dscl . -create /Users/foo

アカウントの詳細表示

$ dscl . -read /Users/foo

また、そのままでは新しく追加したアカウントでのログインができないので、UIDの設定、ホームディレクトリの設定、パスワードの設定も行います。

UIDの設定

$ sudo dscl . -create /Users/foo UniqueID 502

ホームディレクトリの設定

$ sudo dscl . -create /Users/foo NFSHomeDirectory /Users/foo

パスワードの設定

$ sudo passwd foo

以上で、新たに追加したfooアカウントにsudoすることができるようになりました。

PHPのリファレンスカウンティング

2009年5月13日 水曜日

先日、社内にてPHPのリファレンスカウンティングに関する話題が取り上げられたので、リファレンスカウンティングについて少し紹介します。

代入の裏側

PHP(のスクリプティングエンジンであるZend Engine)では、メモリを効率的に利用するため、ある変数を別の変数に代入した際に値の複製をすぐには行わないようになっています。

例えば、以下のコードを実行した場合、

<?php
$a = 'on';
$b = $a;

PHPインタプリタの内部では下図のように、2つの変数がいずれも同一の値を参照するような状態になります。

PHPの内部状態1

PHPの内部状態1

次のように変数の値に対して変更を加えると、値の複製が行われて2つの変数が別々の値を指すようになります。

<?php
$a = 'on';
$b = $a;
$b .= 'e';

この時、内部の状態は以下のようになります。

PHPの内部状態2

PHPの内部状態2

このような手法は一般的にコピーオンライト(Copy-on-write)またはリファレンスカウンティング(Reference Counting)と呼ばれます(PHPコミュニティでは後者が一般的なようです)。

メモリの節約を考える

さきほどの動きを踏まえて、サイズの大きい変数を扱う場合を考えてみます。

<?php
ini_set('memory_limit', '2M');

function get_1MB_data()
{
    return str_pad('', 1024 * 1024, '0');
}

$data1 = get_1MB_data();
$data2 = $data1;
$data3 = $data1;
$data4 = $data1;
$data5 = $data1;

上記のスクリプトは、ini_set()を使ってPHPスクリプトが使用できるメモリ量を2MBに制限してから、1MBの文字列を変数に読み込み、それをさらに4つの変数に代入するという処理になっています。

一見すると、1MB×5個=5MBのメモリが消費されるため、メモリ不足のエラーが起きてしまいそうですが、実際は問題なく動作します。

これは、$data2$data5への代入時に値の複製が行われず、実際には1MB分のメモリしか消費されないためです。

ここで、さらに$data5に文字の追加を行って値の複製を発生させてみましょう。さきほどのスクリプトの最終行を以下のように変更します。

$data5 .= 'a';

すると、予想通りメモリ不足のエラーが発生してスクリプトの実行が中断されます。

$ php test.php
PHP Fatal error:  Allowed memory size of 2097152 bytes exhausted (tried to allocate 1048577 bytes) in test.php on line 14

Fatal error: Allowed memory size of 2097152 bytes exhausted (tried to allocate 1048577 bytes) in test.php on line 14

このような挙動を知っていると、メソッドの引数としてサイズの大きな変数を渡す場合などに、メモリ節約のために明示的に参照渡しとする必要があるかどうかを「メソッド内で引数の値が変更されていないかどうか」で判断することができるようになります。

参考