負け組アーキテクトの憂鬱

メモしておきたいことや読書の記録を淡々と書く。

2007年06月

SunSutidioに同梱されるccで64bitバイナリを生成する

SunSutudio11しか使っていないけれど、たぶんSunStudio12でもいっしょ。

インストーラの指示に従ってccへのpathを通したら、あとはジャンジャンコンパイルすればいいんだけれども、デフォルトではUltraSPARC拡張命令を含まない32bitオブジェクトが出力される。

これを変更するには、''-xarch''オプションを指定する。-xarch=v9bといった具合。ここに指定出来るパラメータで主なものは、以下のようなかんじ。

  • v8:SPARC V8アーキテクチャ向け。32bitバイナリ。
  • v8plus:SPARC V9アーキテクチャの32bitサブセット向け。32bitバイナリ。
  • v8plusa:v8plusにVIS (Visual Instruction Set)1.0とUltraSPARC拡張を加えたもの。32bitバイナリ。
  • v8plusb:v8plusaにVIS 2.0とUltraSPARC-III拡張を加えたもの。32bitバイナリ。
  • v9:SPARC V9アーキテクチャ向け。64bitバイナリ。
  • v9a:v9にVIS 1.0とUltraSPARC拡張を加えたもの。64bitバイナリ。
  • v9b:v9aにVIS 2.0とUltraSPARC-III拡張を加えたもの。64bitバイナリ。

UltraSPARC-III対応のCPUであればv8plusbとv9bの使い分けでいいだろう。ただし、これらのバイナリはUltraSPARC以前のCPUアーキテクチャでは実行できない。

また、64bitでコンパイルする場合、リンクするライブラリもすべて64bit対応している必要がある。64bitバイナリから32bitバイナリはリンクできない。/usr/sfwとか/opt/sfwにインストールされるものの多くは32bitライブラリしか用意されていなかったりするので注意が必要。

32bitと64bitの使い分けは単純に「膨大な数を扱うか否か」で判断して良いと思う。よほど膨大なデータを扱うとか、メチャメチャ沢山コネクションを張るとか。その際はプロセスあたりのリソース上限値の調整も忘れずに(limitやunlimitコマンドで)。

ちなみに、64bitにしたからといってパフォーマンスが劇的に上がることはほとんどない。よほどのことが無い限りない(下がることはある)。当たり前と言えば当たり前の事なんだけれども、よく誤解している人も多い。

個人的には、一昔前の次世代ゲーム機論争のときにNintendo64は64bitだから性能いいんだぜとか、セガサターンは32bitのCPUを2つ積んでいるから64bit級だぜとか、そういう言われ方が多かったことも原因の一つだと思うんだけどまあどうでもいいや。

SunStudio12がリリースされている

http://developers.sun.com/sunstudio/downloads/index.jsp

まだインストールはしていないんだけれども。

最近のSolarisにはgccが添付されているとは言え、gccよりも質の良いコードを吐いてくれるそうなのでインストールしておいて損はないと思う。SDMにメンバ登録する必要はあるけれども、無償で利用できる。ただし、IDE等もまとめて入るので、かなりのディスク容量は食ってしまう。

x86やx64でのコードの質はどうなんだろうか。

mod_proxy_balancerのstickysessionは大文字小文字を区別する

何事もなかったように記事再開。

で、何が困ったかというと、apache httpd-2.2.4に添付のmod_proxy_balancerの挙動。

mod_proxy_balancerについてはこちら。要はmod_proxy系の各種モジュールでproxy先をバランシングできるわけですな。mod_proxy_balancer自体はかなり汎用性のあるモジュールなんだけど、今回困った用途はmod_proxy_ajpとの組み合わせ、つまりmod_jk(2)の代用として使ったときのこと。

たとえばweb層をapache(+mod_ajp +mod_proxy_balancer)の1台、ap層をtomcatの2台構成にしたとき、かつstatefulに振り分けをする必要があって、かつtomcatでセッションレプリケーションが使えない時にstickysessionの機能を使う。

httpd.conf中ではこんなかんじ。

 ProxyPass /webapp/ balancer://testcluster/webapp/ stickysession=ss
 <Proxy balancer://testcluster>
        # r0
        BalancerMember ajp://192.168.100.10:8009 loadfactor=1 route=r0
        # r1
        BalancerMember ajp://192.168.100.11:8009 loadfactor=1 route=r1
 </Proxy>

この設定はssという変数中にr0という文字列が含まれた場合(正しくはss=hogehhuga.r0 のようにピリオド+文字列で終わった場合)にはajp://192.168.100.10:8009に、ajp://192.168.100.11:8009にr1という文字列が含まれた場合にはajp://192.168.100.11:8009にproxyするというもの。変数とは具体的にはCookie、CGI環境変数、urlが利用できるスグレモノだ。

これをtomcatが付加してくれるjsessionidとjvmRouteと組み合わせるとstickysessionを実現できるようになる。2台のtomcatのjvmRouteにそれぞれr0, r1を指定すると、UAがCookieを使える設定になっていればCookieにJSESSIONID=hanamogerahogehoge.r0、Cookieが使えないUAにはURLパラメータとして;jsessionid=gegehogegehoge.r0といった具合に値を付加してくれる。ここでhttpd.confで以下のように設定しておけば、JSESSIONIDにr0が入っていればtomcat(r0)に、r1が入っていればtomcat(r1)にajp接続してくれる。一つのsessionは同じコンテナに接続される、という仕組み。

 ProxyPass /webapp/ balancer://testcluster/webapp/ stickysession=JSESSIONID
 <Proxy balancer://testcluster>
        # r0
        BalancerMember ajp://192.168.100.10:8009 loadfactor=1 route=r0
        # r1
        BalancerMember ajp://192.168.100.11:8009 loadfactor=1 route=r1
 </Proxy>

ただし、stickysession=JSESSIONIDではJSESSIONIDが大文字の場合にしかmatchしない。しかも良くないことにtomcatはCookieではJSESSIONIDと大文字、urlではjsessionidと小文字で変数名を指定する。たとえばCookieを有効にしたUAのみを対象にしたサイトでは問題ないが、Cookieの使えない携帯電話用サイトなども混在差せる場合これでは対応できない。しかも今の仕様ではstickysessionを複数指定することもできないようだ。

とはいえ、この仕様はapacheのbugzillaにも登録されており、一応不具合として認識はされているようだ。該当のbug。とりあえずここのpatchを、httpd-2.2.4のmod_proxy_balancer.cに当たるようにしたものがこれ(ほとんど変わらないけど)。

 --- mod_proxy_balancer.c.orig   Wed May 23 11:09:16 2007
 +++ mod_proxy_balancer.c        Wed May 23 11:58:50 2007
 @@ -112,9 +112,18 @@
                              const char *name)
  {
      char *path = NULL;
 +    char *session_id = NULL;
 +    int  i;
 
 -    for (path = strstr(url, name); path; path = strstr(path + 1, name)) {
 -        path += strlen(name);
 +    session_id= apr_pstrdup(pool, name);
 +    /* Change 'JSESSIONID' to 'jsessionid' to match the value in the url */
 +    if (isupper(name[0])) {
 +      for (i=0;i<=strlen(session_id);i++)
 +       session_id[i] = tolower(session_id[i]);
 +    }
 +
 +    for (path = strstr(url, session_id); path; path = strstr(path + 1, session_id)) {
 +        path += strlen(session_id);
          if (*path == '=') {
              /*
               * Session path was found, get it's value

このpatchを当てることで、とりあえず無邪気にstickysessionを小文字でもmatchするようにしてくれる。本来の挙動(大文字と小文字を厳密に区別する)を期待する場合にはpatchを当ててはいけない。

本来この設定と挙動はどうあるべきか、という議論は、このへんから始まる一連のthreadで話合われているようなので、次回のリリース(httpd-2.2.5?)では何らかの実装の変更があるだろう。