Linuxマシンのメモリ帯域を測定する、Streamの使い方+α

Linuxマシンのメモリ帯域を測定したくなりました。いつもはddコマンドでやっているのですが、どの程度正確なのかいまいち分からないので。。。

メモリ帯域を測定するツールにStreamというものがあります。今回はこれを使います。このエントリにはその使い方と測定結果と考察を書きました。

デフォルトのstreamですと、昨今のコンピュータの性能を鑑みるに測定サイズが小さすぎるので一桁あげています。あげるために、コンパイル方法が少し異なります。具体的には、

gcc -O -mcmodel=large -DSTREAM_ARRAY_SIZE=100000000 stream.c -o stream.100M

と、「-mcmodel=large -DSTREAM_ARRAY_SIZE=100000000」を付加します。

以下、具体的な方法です↓。ちなみに、最適化オプションですが-Oで行いました。-O2ではありません。推奨が-Oだったので、それに準拠した感じです。
# ソースを落としてくる
$ wget http://www.cs.virginia.edu/stream/FTP/Code/stream.c
--2013-07-21 02:56:53--  http://www.cs.virginia.edu/stream/FTP/Code/stream.c
Resolving www.cs.virginia.edu (www.cs.virginia.edu)... 128.143.137.29
Connecting to www.cs.virginia.edu (www.cs.virginia.edu)|128.143.137.29|:80... connected.
HTTP request sent, awaiting response... 200 OK
Length: 19967 (19K) 
Saving to: `stream.c'

100%[===========================================================================================================================================>] 19,967      52.5K/s   in 0.4s    

2013-07-21 02:56:55 (52.5 KB/s) - `stream.c' saved [19967/19967]

# コンパイルする
$ gcc -O -mcmodel=large -DSTREAM_ARRAY_SIZE=100000000 stream.c -o stream.100M

# 測定する
$ ./stream.100M 
-------------------------------------------------------------
STREAM version $Revision: 5.10 $
-------------------------------------------------------------
This system uses 8 bytes per array element.
-------------------------------------------------------------
Array size = 100000000 (elements), Offset = 0 (elements)
Memory per array = 762.9 MiB (= 0.7 GiB).
Total memory required = 2288.8 MiB (= 2.2 GiB).
Each kernel will be executed 10 times.
 The *best* time for each kernel (excluding the first iteration)
 will be used to compute the reported bandwidth.
-------------------------------------------------------------
Your clock granularity/precision appears to be 1 microseconds.
Each test below will take on the order of 120877 microseconds.
   (= 120877 clock ticks)
Increase the size of the arrays if this shows that
you are not getting at least 20 clock ticks per test.
-------------------------------------------------------------
WARNING -- The above is only a rough guideline.
For best results, please be sure you know the
precision of your system timer.
-------------------------------------------------------------
Function    Best Rate MB/s  Avg time     Min time     Max time
Copy:            9542.1     0.167732     0.167678     0.167769
Scale:           9818.7     0.162996     0.162954     0.163030
Add:            11098.8     0.216290     0.216239     0.216334
Triad:          11003.0     0.218197     0.218123     0.218254
-------------------------------------------------------------
Solution Validates: avg error less than 1.000000e-13 on all three arrays
-------------------------------------------------------------

ちなみに↑と同じマシンでddコマンドで測定してみた例↓です。
$ dd if=/dev/zero of=/dev/null bs=100K count=100000
100000+0 records in
100000+0 records out
10240000000 bytes (10 GB) copied, 0.692448 s, 14.8 GB/s

評価:
Streamで10GB/s程度、ddコマンドで14.8GB/sということで、まあおおよそ一致、と言えるのでしょうかね?シングルプロセスによる測定なので、2コアのマシンなら実質この倍使えるということなのでしょう。

↑のマシンのスペックは、
– G540
– Intel(R) Celeron(R) CPU G540 @ 2.50GHz
– DDR3-1600 のDRAM 8GB * 2 (ただし、$ lshw で見てみると、1067MHz駆動のようです)
– Ubuntu 12.04.2 Server AMD64
– Linux Kernel 3.2.0-49-generic #75-Ubuntu SMP
– gcc version 4.6.3 (Ubuntu/Linaro 4.6.3-1ubuntu5)
です。

加えて、手持ちの富士通マシンでも測定してみました。
– Opteron 3280
– DDR3-1333 4GB * 2
– Ubuntu 12.04.2 Server AMD64
– Linux Kernel 3.5.0-36-generic #57~precise1-Ubuntu SMP
– gcc version 4.6.3 (Ubuntu/Linaro 4.6.3-1ubuntu5)

$ gcc -O -mcmodel=large -DSTREAM_ARRAY_SIZE=100000000 stream.c -o stream.100M

$ ./stream.100M 
-------------------------------------------------------------
STREAM version $Revision: 5.10 $
-------------------------------------------------------------
This system uses 8 bytes per array element.
-------------------------------------------------------------
Array size = 100000000 (elements), Offset = 0 (elements)
Memory per array = 762.9 MiB (= 0.7 GiB).
Total memory required = 2288.8 MiB (= 2.2 GiB).
Each kernel will be executed 10 times.
 The *best* time for each kernel (excluding the first iteration)
 will be used to compute the reported bandwidth.
-------------------------------------------------------------
Your clock granularity/precision appears to be 1 microseconds.
Each test below will take on the order of 183660 microseconds.
   (= 183660 clock ticks)
Increase the size of the arrays if this shows that
you are not getting at least 20 clock ticks per test.
-------------------------------------------------------------
WARNING -- The above is only a rough guideline.
For best results, please be sure you know the
precision of your system timer.
-------------------------------------------------------------
Function    Best Rate MB/s  Avg time     Min time     Max time
Copy:            6385.6     0.251072     0.250563     0.251651
Scale:           6222.1     0.257535     0.257150     0.257991
Add:             7221.6     0.332633     0.332334     0.332919
Triad:           7058.7     0.340359     0.340005     0.340577
-------------------------------------------------------------
Solution Validates: avg error less than 1.000000e-13 on all three arrays
-------------------------------------------------------------

$ dd if=/dev/zero of=/dev/null bs=100K count=100000
100000+0 records in
100000+0 records out
10240000000 bytes (10 GB) copied, 1.42714 s, 7.2 GB/s

あまり7GB/s程度ですか。まあ8coresあるので、もっと行けるかもですが。

ちなみに結論としては、
$ dd if=/dev/zero of=/dev/null bs=100K count=100000
はそこそこ精度が良さそうという感じです。Streamをコンパイルするのは面倒ですのでこれで十分感がありますね。

Macでrbenvをgit-cloneしたときに、シンボリックリンクがおかしくなっていた件

rbenvをMacBookに入れてみたら、シンボリックリンクが貼られるべきところに貼られておらず、トラブルになりました。手持ちのMacBookProでは何の問題も起きず。OSは同じなのにどうしてでしょう。

自分のMacBookで、

$ git clone git://github.com/sstephenson/rbenv.git ~/.rbenv
をしてみました。~/.rbenv/bin に移動して、ls -allしてみると↓、
$ cd ~/.rbenv/bin

$ ls -all
total 16
drwxr-xr-x   4 mk  staff  136  7 18 01:25 .
drwxr-xr-x  11 mk  staff  374  7 18 01:25 ..
-rw-r--r--   1 mk  staff   16  7 18 01:25 rbenv
-rwxr-xr-x   1 mk  staff  724  7 18 01:25 ruby-local-exec

$ cat ./rbenv 
../libexec/rbenv
となっていました。

この状態で、~/.bash_profileに対して、
# rbenv
if [ -d $HOME/.rbenv/bin ]; then
    export RBENV_ROOT=$HOME/.rbenv
    export PATH="$RBENV_ROOT/bin:$PATH"
    eval "$(rbenv init -)"
fi
を追加してみました。

そして、反映させると次のようなエラーになりました。
$ source .bash_profile 
-bash: /opt/local/bin/../completions/rbenv.bash: No such file or directory

いろいろと変更してみましたが、こんな感じのエラーが出ていました↓
$ source .bash_profile 
/Users/mk/.rbenv/bin/rbenv: line 1: ../libexec/rbenv: No such file or directory

$ source .bash_profile 
-bash: /Users/mk/.rbenv/bin/rbenv: Permission denied

もちろん、失敗しているので、rbenvコマンドは動きません。

手持ちのMacBookProでrbenvをgit-cloneしてみたところ、正常に動作したのでおかしいと思い、たくさん調べました。すると、正常に動作する方では、~/.rbenv/bin/rbenvにシンボリックリンクが貼られていたのです。正常な状態↓
[mk@macbook: ~/.rbenv/bin]
$ ls -all
total 16
drwxr-xr-x   4 mk  staff  136  7 18 01:21 .
drwxr-xr-x  15 mk  staff  510  7 18 01:32 ..
lrwxr-xr-x   1 mk  staff   16  7 18 01:21 rbenv -> ../libexec/rbenv
-rwxr-xr-x   1 mk  staff  724  7 18 01:20 ruby-local-exec

失敗しているほうでは、シンボリックリンクは貼られていませんでした。うーん、同じgit-cloneでもおかしなことがあるものです。。。

さっそく修正してみました。おかしい状態のrbenvを削除して、シンボリックリンクを貼っています↓
$ cd ~/.rbenv/bin

$ ls -all
total 16
drwxr-xr-x   4 mk  staff  136  7 18 01:25 .
drwxr-xr-x  11 mk  staff  374  7 18 01:25 ..
-rw-r--r--   1 mk  staff   16  7 18 01:25 rbenv
-rwxr-xr-x   1 mk  staff  724  7 18 01:25 ruby-local-exec

# ↓だめな状態
$ cat ./rbenv 
../libexec/rbenv

# 削除
$ rm ./rbenv

# シンボリックリンクを貼る
$ ln -s ../libexec/rbenv ./rbenv

# 確認
$ ls -all rbenv 
lrwxr-xr-x  1 mk  staff  16  7 18 01:21 rbenv -> ../libexec/rbenv

この状態にしたところ、正常に動くようになりました。

Ubuntu、Sinatra、インストール方法、ベンチマーク

追記@2013年10月17日

rbenvのインストールの際に、シンボリックリンクがおかしくなっていることがあります。
Macでrbenvをgit-cloneしたときに、シンボリックリンクがおかしくなっていた件

そのときはこんな処理をしてみるといいと思います↓

$ cd ~/.rbenv/bin

# 削除
$ rm ./rbenv
 
# シンボリックリンクを貼る
$ ln -s ../libexec/rbenv ./rbenv


要約(長い記事なので):
—–
– Ubuntuでsinatraを動かすことが出来ました。
– Nginxで複数のsinatraを集約することが出来ました。
– パフォーマンスも計測しました。
– 最近のCPUであれば1coreあたり2000req/sec程度出るようです。
—–

思うところあってRubyのSinatraをインストールしてベンチマークを取りたくなりました。自然とRESTになるのがいいですね。とは言えたとえばGoogle検索のURLはぜんぜんRESTじゃないので、あまりRESTにこだわる価値はないのかもと思うところもありますが。

環境は、Ubuntu 12系です。おそらくDebian系なら以下の方法で行けると思います。

導入

# 必要なパッケージをインストール
$ aptitude install zlib1g-dev openssl libssl-dev libreadline-dev make gcc g++ git build-essential

# ホームに戻る
$ cd
$ git clone git://github.com/sstephenson/rbenv.git .rbenv
$ echo 'export PATH="$HOME/.rbenv/bin:$PATH"' >> ~/.bashrc
$ echo 'eval "$(rbenv init -)"' >> ~/.bashrc
$ exec $SHELL
$ mkdir -p ~/.rbenv/plugins
$ cd ~/.rbenv/plugins
$ git clone git://github.com/sstephenson/ruby-build.git

# ↓2013年7月16日時点での最新版。少し時間が掛かります($rbenv install --list として手に入るものを探しても良い)
$ rbenv install 1.9.3-p448
$ rbenv rehash
$ rbenv global 1.9.3-p448
$ cd 
$ echo 'install: --no-ri --no-rdoc' >> .gemrc
$ echo 'update: --no-ri --no-rdoc' >> .gemrc
$ gem install thin
$ gem install sinatra

# thinやsinatraを使うのに、rbenv rehashが必要です
$ rbenv rehash

# Exampleを作るために、ディレクトリを作ります
$ mkdir app
$ cd app/

# app.rb, config.ru, thin.config.ip.ymlの中身は下に別記
$ vi app.rb
$ vi config.ru
$ vi thin.config.ip.yml
$ echo 'thin start -C thin.config.ip.yml' >> run.sh
$ echo 'thin stop -C thin.config.ip.yml' >> stop.sh

# 起動
$ sh run.sh

# リクエストを送信して確認
$ curl -i http://localhost:4040/hello/bar
-----
HTTP/1.1 200 OK
Content-Type: text/html;charset=utf-8
Content-Length: 10
X-XSS-Protection: 1; mode=block
X-Content-Type-Options: nosniff
X-Frame-Options: SAMEORIGIN
Connection: keep-alive
Server: thin 1.5.1 codename Straight Razor

Hello bar!
-----

# ポートとプロセスを確認
$ sudo netstat -natp
-----
~中略~
tcp        0      0 0.0.0.0:4040            0.0.0.0:*               LISTEN      933/thin server (0.
~中略~
-----

# 終了
$ sh stop.sh

app.rb
#coding: utf-8
require 'sinatra/base'
class MyApp < Sinatra::Base
  get '/' do
    "Hello World! I am sinatra!"
  end
  get '/hello/:name' do
  # matches "GET /hello/foo" and "GET /hello/bar"
  # params[:name] is 'foo' or 'bar'
  "Hello #{params[:name]}!"
  end
end

config.ru
#coding: utf-8
require File.dirname( __FILE__ ) + '/app.rb'
run MyApp

thin.config.ip.yml
timeout: 30
log: log/thin.log
#environment: production
environment: development
servers: 1
daemonize: false
rackup: config.ru
port: 4040

次はパフォーマンスを見てみます。thinを↑の設定で、NECのサーバーに入れて、富士通サーバーからApache Benchしてみました。

NECサーバーのスペック(いわゆる鼻毛鯖)
– Celeron G540
– DRAM 8GB * 2
– 500GBHDD
– Ubuntu 12.04 Server AMD64
– Linux Kernel 3.2.0-45-generic #70-Ubuntu SMP

ネットワークトポロジー
NECサーバー <= GbE => GbEスイッチングハブ <= GbE => 富士通サーバー

# NECサーバーに対して、富士通サーバーからApache Benchしています
$ ab -n 100000 -c 100 http://192.168.1.3:4040/hello/performance
-----
~~~
Server Software:        thin
Server Hostname:        192.168.1.3
Server Port:            4040

Document Path:          /hello/performance
Document Length:        18 bytes

Concurrency Level:      100
Time taken for tests:   47.750 seconds
Complete requests:      100000
Failed requests:        0
Write errors:           0
Total transferred:      25400000 bytes
HTML transferred:       1800000 bytes
Requests per second:    2094.22 [#/sec] (mean)
Time per request:       47.750 [ms] (mean)
Time per request:       0.478 [ms] (mean, across all concurrent requests)
Transfer rate:          519.47 [Kbytes/sec] received
~~~
-----

評価:
2094 req/sec程度でした。1プロセスでこの速度というのは、そこそこ高速と言えるのではないでしょうか。このアクセスを捌いているときのNECサーバーの様子を以下に示します。
$ dstat
You did not select any stats, using -cdngy by default.
----total-cpu-usage---- -dsk/total- -net/total- ---paging-- ---system--
usr sys idl wai hiq siq| read  writ| recv  send|  in   out | int   csw 
  1   0  99   0   0   0|  16k   51k|   0     0 |   0     0 | 149    98 
 46   2  50   0   0   2|   0     0 | 924k 1233k|   0     0 |4514   254 
 42   3  50   0   0   5|   0     0 | 924k 1232k|   0     0 |4490   232 
 46   3  50   0   0   1|   0     0 | 927k 1237k|   0     0 |4528   248 
 44   1  50   0   0   5|   0     0 | 925k 1232k|   0     0 |4496   235
こんな感じでした。2コアのマシンですので、1コアはほぼ完全に使い切っているということになります。また、CPU使用率のsysのところでは3となっていますが、これはTCP/IPの処理ではないでしょうか。
ちなみにApache + PHPでの”Hello, world”では、8295 req/secでした。

次に、thinプロセスを増やし、nginxに集約させてみます。今回はthinプロセスをUnix Domain Socketで複数動かし、Nginxをリバースプロキシにします。

先ほど作ったappをコピーしてapp2を作りそこに移動して、thin.config.ip.ymlを書き換えます。
$ cd
$ cp -R app/ app2/
$ cd app2
$ mkdir sock
$ vi thin.config.ip.yml

thin.config.ip.yml
environment: development
timeout: 30
log: log/sinatra.log
pid: pid/sinatra.pid
max_conns: 2048
max_persistent_conns: 1024
require: []
wait: 30
daemonize: true
socket: sock/sinatra.sock
servers: 2

ひとまず「servers: 2」、つまりthinプロセスを2個作ります。

次にNginxの設定をします。
# Nginxをインストールします
$ sudo aptitude install nginx

# 設定ファイルのバックアップを取っておきます。
$ sudo cp /etc/nginx/sites-available/default /etc/nginx/sites-available/default.bk

# 設定を書き換えます。下に別記しています。
$ sudo vi /etc/nginx/sites-available/default

# 走らせます
$ sudo /etc/init.d/nginx start

/etc/nginx/sites-available/default の中身(注意!/home/kawa/~略~となっていますが、ユーザー名は人のよって異なるので、自分のユーザー名に書き換えてください)
server{
  listen 8080;
  #server_name example.com;
  proxy_set_header  X-Real-IP       $remote_addr;
  proxy_set_header  X-Forwarded-For $proxy_add_x_forwarded_for;
  proxy_set_header  Host            $http_host;
  proxy_redirect    off;
  proxy_max_temp_file_size          0;
  location / {
    proxy_pass http://sinatra;
  }
}
upstream sinatra {
  server unix:/home/kawa/app2/sock/sinatra.0.sock;
  server unix:/home/kawa/app2/sock/sinatra.1.sock;
}

Apache Benchの前に、きちんとNginxとthinの設定がうまく行っているか確認します。
$ curl -i http://localhost:8080/
HTTP/1.1 200 OK
Server: nginx/1.1.19
Date: Tue, 16 Jul 2013 02:13:25 GMT
Content-Type: text/html;charset=utf-8
Content-Length: 26
Connection: keep-alive
X-XSS-Protection: 1; mode=block
X-Content-Type-Options: nosniff
X-Frame-Options: SAMEORIGIN

Hello World! I am sinatra!

↑きちんとNginxを経由していますね。さて、Apache Benchしてみます。

# NECサーバーに対して、富士通サーバーからApache Benchしています
$ ab -n 100000 -c 100 http://192.168.1.3:4040/hello/performance
-----
~~~
Server Software:        nginx/1.1.19
Server Hostname:        192.168.1.3
Server Port:            8080

Document Path:          /hello/performance
Document Length:        18 bytes

Concurrency Level:      100
Time taken for tests:   33.129 seconds
Complete requests:      100000
Failed requests:        0
Write errors:           0
Total transferred:      26900000 bytes
HTML transferred:       1800000 bytes
Requests per second:    3018.54 [#/sec] (mean)
Time per request:       33.129 [ms] (mean)
Time per request:       0.331 [ms] (mean, across all concurrent requests)
Transfer rate:          792.96 [Kbytes/sec] received
~~~
-----

評価:
前回は2000 req/sec程度でしたが、1.5倍の速度になりました。素直に2倍にはなってくれませんね。Nginxを経由しますので遅くなるのでしょうか。また、dstatを見てみます。
$ dstat
You did not select any stats, using -cdngy by default.
----total-cpu-usage---- -dsk/total- -net/total- ---paging-- ---system--
usr sys idl wai hiq siq| read  writ| recv  send|  in   out | int   csw 
 85  10   0   0   0   5|   0     0 |1370k 1872k|   0     0 |  11k   15k
 84  12   0   0   0   5|   0     0 |1361k 1859k|   0     0 |  12k   14k
 81  12   0   0   0   6|   0    12k|1363k 1862k|   0     0 |  11k   15k
 86  10   0   0   0   4|   0     0 |1369k 1870k|   0     0 |  11k   14k
 82  12   0   0   0   6|   0     0 |1383k 1890k|   0     0 |  11k   13k
これを見るに、CPUを完全に使い切っています。ということは、プロセスを増やしても性能の向上は期待できなさそうです。

次に、4つのthinプロセスにしてみます。おそらく伸びませんが。。。
thin.config.ip.ymlの「servers」を4に、/etc/nginx/sites-available/default の「upstream sinatra」のところに追加、で出来ます。sinatraとnginxのrestartを忘れずにしましょう。

# NECサーバーに対して、富士通サーバーからApache Benchしています
$ ab -n 100000 -c 100 http://192.168.1.3:4040/hello/performance
-----
~~~
Server Software:        nginx/1.1.19
Server Hostname:        192.168.1.3
Server Port:            8080

Document Path:          /hello/performance
Document Length:        18 bytes

Concurrency Level:      100
Time taken for tests:   37.284 seconds
Complete requests:      100000
Failed requests:        0
Write errors:           0
Total transferred:      26900000 bytes
HTML transferred:       1800000 bytes
Requests per second:    2682.09 [#/sec] (mean)
Time per request:       37.284 [ms] (mean)
Time per request:       0.373 [ms] (mean, across all concurrent requests)
Transfer rate:          704.57 [Kbytes/sec] received
~~~
-----

評価:
2個のプロセスのときよりも若干遅くなってしまいました。予想通り、2個のthinプロセスでこのマシンは限界を迎えるので、4個のthinプロセスを立てても全くの無駄でした。

蛇足:
富士通サーバー(Opteron 3280)をサーバーにしてやってみました。
– thinプロセス 8個
です。
Server Software:        nginx/1.1.19
Server Hostname:        192.168.1.2
Server Port:            8080

Document Path:          /hello/performance
Document Length:        18 bytes

Concurrency Level:      100
Time taken for tests:   11.275 seconds
Complete requests:      100000
Failed requests:        0
Write errors:           0
Total transferred:      26900000 bytes
HTML transferred:       1800000 bytes
Requests per second:    8869.56 [#/sec] (mean)
Time per request:       11.275 [ms] (mean)
Time per request:       0.113 [ms] (mean, across all concurrent requests)
Transfer rate:          2329.99 [Kbytes/sec] received

1万req/sec近く出ています。さすが8core、、、と言いたいところですが、注目するべき点は、
>Time per request: 11.275 [ms] (mean)
でしょう。先ほどのNECサーバー(Celeron G540)のときは、
>Time per request: 37.284 [ms] (mean)
でした。うーん、どういうことでしょう。今まで様々なベンチマークを取って来ましたが、常にCeleron G540 > Opteronでした。何かおかしい気がします。。。現在調査中です。。。G540サーバーはもっと良い成績が出ると思います。

Nginxを使わずにsinatraを単独で(port:4040)動かしてみると次のようになりました。
G540(鯖): Time per request: 47.531 [ms] (mean)
Opteron(鯖): Time per request: 36.184 [ms] (mean)

うーん、そこまで差があるわけではないですね。不思議です。Opteronの方は綺麗に集約されるけれども、G540の方は集約されないということみたいですが、きっと何かがおかしいはず。。。

CentOS、Nginx、php-fpm、git-hookの設定

表題のものを動かしたかったわけです。割とはまったので記録しておきます。全てのコマンドはrootで行なってください。

nginxのルートディレクトリは、/var/www/nginx/としました。nginxの設定で、fastcgi_paramについて、$document_rootを使いたかったのですが使ってみるとうまくいかないので諦めて直書きです。悲しい。

portは8765としました。ドメインがexample.comとなっていますが、自身のドメインに書き換えてください。

$ yum update
$ yum install nginx php-fpm.x86_64
$ chkconfig nginx on
$ chkconfig php-fpm on
$ vi /etc/nginx/conf.d/default.conf

/etc/nginx/conf.d/default.conf
#
# The default server
#
server {
    listen       8765;
    server_name  example.com;
        #root    /var/www/nginx;
    #charset koi8-r;

    #access_log  logs/host.access.log  main;

    location / {
        #root   /usr/share/nginx/html;
                root    /var/www/nginx;
        index  index.html index.htm;
    }

    error_page  404              /404.html;
    location = /404.html {
        root   /usr/share/nginx/html;
    }

    # redirect server error pages to the static page /50x.html
    #
    error_page   500 502 503 504  /50x.html;
    location = /50x.html {
        root   /usr/share/nginx/html;
    }

    # proxy the PHP scripts to Apache listening on 127.0.0.1:80
    #
    #location ~ \.php$ {
    #    proxy_pass   http://127.0.0.1;
    #}

    # pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
    #
    location ~ \.php$ {
        root           html;
        fastcgi_pass   127.0.0.1:9000;
        fastcgi_index  index.php;
        fastcgi_param  SCRIPT_FILENAME  /var/www/nginx$fastcgi_script_name;
        include        fastcgi_params;
    }

    # deny access to .htaccess files, if Apache's document root
    # concurs with nginx's one
    #
    #location ~ /\.ht {
    #    deny  all;
    #}
}

/var/lib/hogeにいろいろなPHPのファイルを入れるとして(git絡みで直接/var/www/nginx/hogeには出来ない)のディレクトリのシンボリックリンクを貼ります。「/」のあるなしで変わってくるので注意です。
$ ln -s /var/lib/hoge /var/www/nginx/hoge

動かないというときは、
– nginxやphp-fpmが立ち上がっているか($netstat -natpで確認可能です)
– iptablesでnginxのポートを開けているか
– /var/log/nginx/error.log を見る
– ディレクトリやファイルのパーミションの確認
あたりをしてみてください。

加えてgit-hookの設定です。はまりどころ多数ですので記録厨になります。この通り↓やったら出来ました。

git pushで本番環境にデプロイ


なにをしたいかと言えば、
– ローカルにあるレポジトリhogeを、gitサーバー兼検証サーバー(Aサーバーとする)にgitでpush
– Aサーバー、ユーザーgituserで↑を受け取り、git-hookで/var/lib/hoge にpush
– /var/www/nginx/ に、/var/lib/hogeのシンボリックリンクを貼る
という行為です。いろいろとやってみましたがうまく行きませんでしたが↑のリンクでうまくいきました。具体的な作業ログを残しておきます。

$ su root
$ cd /var/lib
$ git clone /home/gituser/repositories/hoge.git hoge
$ chown -R gituser:gituser hoge/
$ ln -s /var/lib/hoge /var/www/nginx/hoge
$ su gituser
$ vi /home/gituser/repositories/hoge-app.git/hooks/post-receive
$ chmod 700 /home/gituser/repositories/hoge-app.git/hooks/post-receive
$ cat /home/gituser/repositories/hoge-app.git/hooks/post-receive
#!/bin/sh
cd /var/lib/hoge && git --git-dir=.git pull

UbuntuのPHP5の環境づくり

意外と載っていない感がありましたので。。。
ついでにRedisとMongoDBも使えるようにしてみました。

ぜんぶのコマンドにsudoを入れるか、rootになる必要があります。

$ aptitude install php5 php5-dev php-pear
$ pecl install redis
$ echo "extension=redis.so" >> /etc/php5/cli/php.ini
$ echo "extension=redis.so" >> /etc/php5/apache2/php.ini 
$ pecl install mongo
$ echo "extension=mongo.so" >> /etc/php5/cli/php.ini 
$ echo "extension=mongo.so" >> /etc/php5/apache2/php.ini 

PHPでRedisとMongoDBが使えるかどうかの確認です↓。
$ php -m | grep redis 
redis

$ php -m | grep mongo
mongo

確認のためのコードです(Redisだけ)。
$ cat redis.php 
<?php

$redis = new Redis();
$redis->connect('127.0.0.1', 6379);

$max = 10000;
echo 'records: ' . $max . "\n";

$start = microtime(true);
$pipe = $redis->multi(Redis::PIPELINE);
for ($i = 0; $i < $max; $i++){
	$tmp = $redis->incr('counter');
}
$pipe->exec();
echo '(PIPELINED) time: ' . (double) (microtime(true) - $start) . " [sec]\n";

$start = microtime(true);
for ($i = 0; $i < $max; $i++){
	$tmp = $redis->incr('counter');
}
echo '(RAW)       time: ' . (double) (microtime(true) - $start) . " [sec]\n";

出力(Raspberry PI 512MBモデル、Raspbianです):
$ php redis.php 
records: 10000
(PIPELINED) time: 0.91323804855347 [sec]
(RAW)       time: 6.0866370201111 [sec]

PHPやRedis、MongoDBのバージョン等を表記しておきたく為りましたがめんどうなのでやめておきます。

ちなみに、Opteron3280、Ubuntu12.04で行なってみたところ、
$ php redis.php 
records: 100000
(PIPELINED) time: 0.3497359752655 [sec]
(RAW)       time: 6.9338431358337 [sec]
でした。PIPELINEを使えば30万req/sec程度になるわけですね。