Hatena::Groupsubtech

名称未設定♥

2009-06-24

perl-rename-buffer - package名にrename-bufferしてくれるelisp #2

16:52 |  perl-rename-buffer - package名にrename-bufferしてくれるelisp #2 - 名称未設定♥ を含むブックマーク はてなブックマーク -  perl-rename-buffer - package名にrename-bufferしてくれるelisp #2 - 名称未設定♥

g:subtech:id:hirose31:20090613:1244914640 の続き。

コードスケッチのときとか、ひとつのファイルにmain部とpackage宣言とが混在してるときに、ファイルの下の方のpackage宣言をひろってrename-bufferしちゃうので、最初のn行までにpackage宣言があるときのみその名でrename-bufferするようにしてみた。

(defun plcmp-get-current-package-name-first (&optional limitline)
  "nil or string"
  (let ((re (rx-to-string `(and bol
                                (* space)
                                "package"
                                (* space)
                                (group
                                 (regexp ,plcmp-perl-package-re))
                                (* not-newline)
                                ";")))
        (bound (if (not limitline)
                   nil
                 (line-end-position limitline)))
        )
    (save-excursion
      (goto-char (point-min))
      (when (re-search-forward re bound t)
        (match-string-no-properties 1)))))

(defun perl-rename-buffer ()
  (interactive)
  (let ((package-name (plcmp-get-current-package-name-first 16)))
    (when package-name
      (rename-buffer package-name t))))
トラックバック - http://subtech.g.hatena.ne.jp/hirose31/20090624

2009-06-17

AnyEvent::FastPing 解体新書

15:40 |  AnyEvent::FastPing 解体新書 - 名称未設定♥ を含むブックマーク はてなブックマーク -  AnyEvent::FastPing 解体新書 - 名称未設定♥

多ノードにすばやくpingpongする必要があったのでAnyEvent::FastPingを使ってみたんですが、内部的にどういう処理をしてるのか気になってメモったので残しておきたいと思います。

f:id:hirose31:20090617151700j:image

  • pipe(2)を2回実行して、2ペア、都合4つのfdを作る
  • BOOTブロック(=useされたタイミング?)でpthread_create(3)してワーカースレッドを作る
  • メインスレッドとワーカースレッドは、最初に作ったpipe(2)なfdを介して互いのイベントを発火させる(図の左上と、下部の緑色の箱と矢印)
    • 例: メインスレッドが、pipe(2)なfdにwriteすると、繋がってる他方のfd(こっちはワーカスレッドが持ってる)がread可能になる。ほんで、これらのfdはepoll(7)やselect(2)で監視しているので、非同期にそのコールバックを実行可能になるわけです。
  • あと、ICMP用のSOCK_RAWなsocketも作ってて、これもepoll(7)で監視してる
    • ワーカースレッドの中でpingを送りまくる (sendto(2)しまくる)。応答は待たない。気にせず送りまくる。
    • ほどなくしてpongが返ってくると、read可能になるのでメインスレッドのそのコールバックでrecvfrom(2)しまくって結果を表示しまくる

追記。

「epoll(7)やselect(2)で監視している」のepoll(7)だとかselect(2)だとかは AnyEvent が隠蔽してくれるので、epoll(7)だとかselect(2)だとかのAPIの違いは気にする必要がないです。

こんな感じ:

our $THR_RES_W = AnyEvent->io (fh => $THR_RES_FH, poll => 'r', cb => sub {
   my $sv = _read_res
      or return;

   $sv->();
});

に、AnyEventのI/O監視のAPIを使うだけで OK です。

自分の環境 (Linux) では、use AnyEvent だけだと select(2) が使われて、

use AnyEvent;
use EV;

するとepoll(7)が使われました。


(港区在住 非同期野郎Pチーム 31)

トラックバック - http://subtech.g.hatena.ne.jp/hirose31/20090617

2009-06-13

perl-rename-buffer - package名にrename-bufferしてくれるelisp

02:37 |  perl-rename-buffer - package名にrename-bufferしてくれるelisp - 名称未設定♥ を含むブックマーク はてなブックマーク -  perl-rename-buffer - package名にrename-bufferしてくれるelisp - 名称未設定♥

Emacsでファイルを開くとそのバッファ名はファイル名になります。

ですので、"なんとか/Server.pm" なファイルをいくつか開いていると、anythingなどでのバッファ選択では "Server.pm" がいっぱい出てきてどれがどれだかわかりません。

f:id:hirose31:20090614022231p:image


バッファ名をpackage名にすれば区別がつくようになるんですが、いちいち手でrename-bufferするのはめんどうです。

で、なんかいい方法ないですかねー?ときいたら id:IMAKADO がさくっとファイルを開いたらバッファ名をpackage名にしてくれるのを作ってくれました。

これが使用後。

f:id:hirose31:20090614022232p:image

ハラショー!!

g:subtech:id:hirose31:20090624:1245829941 に続きます……



トラックバック - http://subtech.g.hatena.ne.jp/hirose31/20090613

2009-05-28

mod_perl 2で、VirtualHostごとのErrorLogじゃなくてserver contextのErrorLogにエラーログなどが出力されちゃう

17:07 |  mod_perl 2で、VirtualHostごとのErrorLogじゃなくてserver contextのErrorLogにエラーログなどが出力されちゃう - 名称未設定♥ を含むブックマーク はてなブックマーク -  mod_perl 2で、VirtualHostごとのErrorLogじゃなくてserver contextのErrorLogにエラーログなどが出力されちゃう - 名称未設定♥

# zakkuri httpd.conf

LoadModule perl_module modules/mod_perl.so

ErrorLog  "/var/log/httpd/default/default.err"

<VirtualHost *>
  ServerName   curry.example.com

  ErrorLog  "/var/log/httpd/example.com/curry.err"

  PerlOptions  +SetupEnv +Parent
  <Location />
    SetHandler           modperl
    PerlResponseHandler  OrenoHandler
  </Location>
</VirtualHost>

な構成で、OrenoHandler 内で

print        "OrenoTest: STDOUT\n";
print STDERR "OrenoTest: STDERR\n";
warn         "OrenoTest: warn";
my $v1 = "2:" + 3;
eval q[my $v2 = "3:" + 4;];
(undef) . "xxx";
my %h1 = qw(foo bar baz);
die "OrenoTest: die";

とすると、VirtualHostのErrorLogのcurry.errじゃなくて、server contextのErrorLogのdeault.errに全部出ちゃう。

VirtualHostが複数あると、ログが混ざってどのVirtualHostのか判別しづらくなるのでちゃんとVirtualHostのErrorLogに吐かせてあげたい。


http://perl.apache.org/docs/2.0/api/Apache2/Log.html#Virtual_Hosts

に書いてあるように、httpd.confで

-  PerlOptions  +SetupEnv +Parent
+  PerlOptions  +SetupEnv +Parent +GlobalRequest

して、OrenoHandler で

use Apache2::Log ();
$SIG{__WARN__} = \&Apache2::ServerRec::warn;

してあげると、curry.errにはこのように吐かれるようになる。

[warn] OrenoTest: warn at ...
[warn] Argument "3:" isn't numeric in addition (+) at (eval 8) line 1.\n
[warn] Use of uninitialized value in concatenation (.) or string at ...
[warn] Odd number of elements in hash assignment at ...

一方で、default.errにはこのように吐かれる。

Argument "2:" isn't numeric in addition (+) at ...
Useless use of concatenation (.) or string in void context at ...
OrenoTest: STDERR

つまり、

  • warn
  • die
  • eval
  • 実行時エラー?

はVirtualHostのErrorLogに出るようになったけど、

  • STDERR
  • use warningsの警告?

は依然としてserver contextのErrorLogに出てしまう。


まぁこれでだいたいいいかなぁとは思うんですが、2点、残糞感がある感じす。

  1. 残りのSTDERRとwarningsもVirtualHostのErrorLogに出せないか
  2. PerlOptions の GlobalRequest ってなんか副作用ないか心配

しゅ〜しゅ〜

追記 2009-07-10

STDERR と Apache2::ServerRec::warn を tie して、print STDERR を Apache2::ServerRec::warn にしちゃう、というテクを同僚に教えてもらいました。

use Apache2::Log ();
$SIG{__WARN__} = \&Apache2::ServerRec::warn;
{
    package Oreno::_tie_stderr;
    sub TIEHANDLE { bless {}, shift }
    sub PRINT     { shift; Apache2::ServerRec::warn(@_) }
    tie *STDERR, __PACKAGE__;
}

これで print STDERR も VirtualHosts 毎の ErrorLog に出力されるようになったので、残すは

  • use warningsの警告?

のみです。

トラックバック - http://subtech.g.hatena.ne.jp/hirose31/20090528

2009-03-08

Perlで、占有しているメモリ量をpackage毎に知る方法

23:37 |  Perlで、占有しているメモリ量をpackage毎に知る方法 - 名称未設定♥ を含むブックマーク はてなブックマーク -  Perlで、占有しているメモリ量をpackage毎に知る方法 - 名称未設定♥

Apache2::Status では、条件が揃えば package 毎に喰ってるメモリ量を知ることができます。

StatusTerseSizeMainSummary

With this option On and the B::TerseSize module installed, a "Memory Usage" will be added to the Apache2::Status main menu. This option is disabled by default, as it can be rather cpu intensive to summarize memory usage for the entire server. It is strongly suggested that this option only be used with a development server running in -X mode, as the results will be cached.

mod_perl: Apache2::Status - Embedded interpreter status information

mod_perl環境、普通のスクリプトとか、Perlで書いたdaemonでも使えるといいなと思ったので、ソースみてコピペってみました。

use B::TerseSize;
use Devel::Symdump;

my $stab = Devel::Symdump->rnew("main");
my %size;
for my $package ("main", $stab->packages) {
    my($subs, $opcount, $opsize) = B::TerseSize::package_size($package);
    $size{$package} = $opsize;
}
for my $package (sort {$size{$b}<=>$size{$a}} keys %size) {
    printf "%-24s %8d [KB]\n", $package, $size{$package}/1024;
}

ENDブロックでくるんでスクリプトが終了するときにサマリを出力するようにしたり、シグナルハンドラで出力するようにするといいんじゃないかと思います。

トラックバック - http://subtech.g.hatena.ne.jp/hirose31/20090308