Hatena::Groupdann

dann's blog このページをアンテナに追加 RSSフィード

Fork me on GitHub

2008-12-29

Perl関連で新しく始めたいこと

Perl関連で新しく始めたいこと - dann's blog を含むブックマーク はてなブックマーク - Perl関連で新しく始めたいこと - dann's blog Perl関連で新しく始めたいこと - dann's blog のブックマークコメント

来年は、Perlに関しては、少しXSを触れるようにしたいなと。割とcとかc++でwrapして使いたいなって思う事が結構あるので、自分でできるようにしたいなぁと。

perlxstut読むとこからですかね。これもWAF作りと同じで気長に来年やってこうと思ってます。

WAFに必要な要素

WAFに必要な要素 - dann's blog を含むブックマーク はてなブックマーク - WAFに必要な要素 - dann's blog WAFに必要な要素 - dann's blog のブックマークコメント

この1ヶ月はPerlRubyのWAFのコードは大分読んで、必要な要素がわかったので、angelosのクラス構成をベースに簡単にまとめてみました。

http://github.com/dann/angelos/tree/master

WAF Core

  • Application Class (Angelos.pm)
    • WAF全体のsetup
  • Component
    • Controller
    • View
    • (Model)
  • Component Loader
    • Componentの読み込みと組み立て(Pluginの組み込み)
    • mstCatalystでDIコンテナを使いたいといっててのはここの部分ですね
  • Engine
  • Dispatcher
    • Routing + Controllerへのdispatch
  • Engine拡張
    • Middleware
      • request handlerをwrap
  • プラグイン機構 (Angelos::Class)
    • Angelos::Class::Hookable
    • hook機構によるプラグイン機構。MouseX::Plaggerizeからfork予定.
  • Angelos::Class::Mixinable
    • Mixin機構による拡張を実現するプラグイン機構。MooseX::Object::Pluggableのmouse port.
  • Script
    • フレームワーク系のhelper script管理クラス
  • WAFに必要なその他の機能(必須ではない機能)
    • Authorization+Authentication
    • Session
      • HTTP::Sessionベースで
    • I18N

Session, Authentication, I18Nは、フレームワークのPluginという形に最終的にはなるかなと思ってます。Session, AuthenticationはMiddlewareレイヤでやるべきかは少し悩んではいますが。

フレームワーク周辺機能

Webアプリで必要になる要素はデフォルトで用意しておきたいなと思ってます。コア機能という形でいれこむかはさておき、WAFとconfigurationやモデルが共有できるような仕組みを提供したいと思っています。

  • CLI
    • アプリのCLIのベースクラス
  • Job Queue
    • これはまだ未コミット。

angelosのクラス構成

ここ数日でangelosもWAFとしての骨格は整ってきたかなという印象です。コードもここ数日で大分整理したので、HTTP::Engineを使ったWAFの例としては参考にできる点もあるのではないかと思います。

現在のクラス構成は以下のようになっています。

.
|-- Angelos
|   |-- CLI
|   |   |-- Command.pm
|   |   `-- Help.pm
|   |-- CLI.pm
|   |-- Class
|   |   |-- Hookable
|   |   |   `-- Plugin.pm
|   |   |-- Hookable.pm
|   |   `-- Mixinable.pm
|   |-- Component
|   |   `-- Loader.pm
|   |-- Component.pm
|   |-- Config
|   |   |-- Loader.pm
|   |   |-- Schema.pm
|   |   `-- Validator.pm
|   |-- Config.pm
|   |-- Context
|   |   `-- Mixin
|   |-- Context.pm
|   |-- Controller
|   |   `-- Mixin
|   |-- Controller.pm
|   |-- Debug
|   |   |-- Components.pm
|   |   |-- MemoryUsage.pm
|   |   `-- Routes.pm
|   |-- Dispatcher
|   |   |-- Dispatch.pm
|   |   `-- Routes
|   |       `-- Builder.pm
|   |-- Dispatcher.pm
|   |-- Engine
|   |   |-- ModPerl.pm
|   |   |-- Plugin
|   |   |   `-- Session.pm
|   |   `-- Plugin.pm
|   |-- Engine.pm
|   |-- Exception.pm
|   |-- Exceptions.pm
|   |-- Home.pm
|   |-- I18N.pm
|   |-- Logger.pm
|   |-- MIMETypes.pm
|   |-- Manual
|   |   `-- Tutorial.pod
|   |-- Manual.pm
|   |-- Middleware
|   |   |-- Builder.pm
|   |   |-- Profile.pm
|   |   `-- Unicode.pm
|   |-- Middleware.pm
|   |-- Script
|   |   |-- Command
|   |   |   |-- Console
|   |   |   |   `-- Plugin
|   |   |   |-- Console.pm
|   |   |   |-- Gen
|   |   |   |   `-- Flavor
|   |   |   |       `-- App.pm
|   |   |   |-- Gen.pm
|   |   |   |-- Po.pm
|   |   |   `-- Server.pm
|   |   `-- Help.pm
|   |-- Script.pm
|   |-- SessionBuilder.pm
|   |-- Utils.pm
|   |-- View
|   |   |-- Plugin
|   |   `-- TT.pm
|   `-- View.pm
|-- Angelos.pm

今後のTODO

今後は、以下のようなものを追加していきたいなと。

  • WAFの基本機能の追加
    • Controller: redirect, forward, detachなど。
    • View
      • displayメソッドの実装(merb likeな)
  • Modelの統合
    • どのように実現するか要検討
  • Authorization+Authetication対応
    • 今みている限りだとCatalystの認証機構のportが一番筋がよさそうです
  • Job Queueへの対応
  • $c依存にするか否かの決定

HTTP::Engineでmod_perl対応のアプリを作る方法

HTTP::Engineでmod_perl対応のアプリを作る方法 - dann's blog を含むブックマーク はてなブックマーク - HTTP::Engineでmod_perl対応のアプリを作る方法 - dann's blog HTTP::Engineでmod_perl対応のアプリを作る方法 - dann's blog のブックマークコメント

angelosをmod_perl対応にしてみた

http://github.com/dann/angelos/tree/master/lib/Angelos/Engine/ModPerl.pm

作るポイントは以下の2点だけ

使うときは、PerlResponseHandlerに上記のクラスを指定すればいいだけです。とても簡単ですね。Yappo++

Test::TCP+Devel::NYTProfでWAFのパフォーマンスチューニング

| Test::TCP+Devel::NYTProfでWAFのパフォーマンスチューニング - dann's blog を含むブックマーク はてなブックマーク - Test::TCP+Devel::NYTProfでWAFのパフォーマンスチューニング - dann's blog Test::TCP+Devel::NYTProfでWAFのパフォーマンスチューニング - dann's blog のブックマークコメント

HTTP::Engineから拝借したんですが、Test::TCP + Devel::NYTProfの組み合わせで、WAFのprofilingが簡単にできます。

#!/usr/bin/env perl
use strict;
use HTTP::Engine;
use LWP::UserAgent;

my $module = shift || 'ServerSimple';
my $port = shift || empty_port();
my $loop = shift || 100;

test_tcp(
    client => sub {
        my $port = shift;
        my $ua   = LWP::UserAgent->new;
        for ( 0 .. $loop ) {
            $ua->get("http://localhost:$port/");
        }
    },
    server => sub {
        my $port = shift;
        if ( !$ENV{NO_NYTPROF} ) {
            require Devel::NYTProf;
            $ENV{NYTPROF} = 'start=no';
            Devel::NYTProf->import;
            DB::enable_profile();
            $SIG{TERM} = sub { DB::_finish(); exit; };
        }
        my $engine = TestApp::Web->new(
            server => $module,
            port   => $port,
        );
        $engine->setup;
        $engine->run;

    },
);

tokuhiromさんのTest::TCPは素晴らしいですね。これで大分チューニングがしやすくなりました。

# 上記のスクリプトは以下の場所にいれてあります。

http://github.com/dann/angelos/tree/master/tools

Module::Setupのflavorのpack, unpack

Module::Setupのflavorのpack, unpack - dann's blog を含むブックマーク はてなブックマーク - Module::Setupのflavorのpack, unpack - dann's blog Module::Setupのflavorのpack, unpack - dann's blog のブックマークコメント

pack, unpackするスクリプトを用意しておくことで、大分作りやすくなりました。

pack_flavor.sh

~/.module-setup/flavors/angelos/にあるflavorをpackして1つのファイルにまとめる。

#!/bin/sh
rm -f lib/Angelos/Script/Gen/Flavor/App.pm
module-setup --pack Angelos::Script::Gen::Flavor::App angelos > lib/Angelos/Script/Gen/Flavor/App.pm

unpack_flavor.sh

#!/bin/sh
module-setup --init --flavor-class=+Angelos::Script::Gen::Flavor::App angelos

以下の場所に展開される

~/.module-setup/flavors/angelos

使い方は、

  • チェックアウトして、unpack_flavor.sh
  • flavor編集 vim ~/.module-setup/flavors/angelos/templtae/**.pm
  • pack_flavor.sh

依存モジュールのメモリ使用量調査

依存モジュールのメモリ使用量調査 - dann's blog を含むブックマーク はてなブックマーク - 依存モジュールのメモリ使用量調査 - dann's blog 依存モジュールのメモリ使用量調査 - dann's blog のブックマークコメント

WAFのメモリ使用量を抑えたいということで、モジュールをuseしたときのメモリを調べてみる。こないだ書いたエントリのスクリプトを少し見やすくしたもの。

#!/usr/bin/env perl
use strict;
use warnings;
use Devel::MemUsed;
use Module::Depends;

main();

sub main {
    my $memory_record = record_memory_usage();
}

sub record_memory_usage {
    my $deps = Module::Depends->new->dist_dir('.')->find_modules;
    foreach my $module ( keys %{ $deps->requires } ) { 
        my $pid = fork();
        if ($pid) {

            # parent
            wait();
        }
        elsif ( defined $pid ) { 
            my $memused = Devel::MemUsed->new;
            eval "use $module";
            print sprintf( "%35s %08d", $module, $memused ) . "\n";
            exit();
        }
        else {
            die "fork error : $!";
        }
    }   
}

出力結果をソート

#!/bin/sh
perl tools/module_memory.pl | sort -k 2

Angelosの依存モジュールで調べたら以下のような感じ。

                     Devel::MemUsed 00005128
                               YAML 00005232
        Log::Dispatch::Configurator 00017208
                  String::CamelCase 00018848
                 UNIVERSAL::require 00020808
                 Filter::Util::Call 00022600
                Devel::InnerPackage 00023688
  Log::Dispatch::Configurator::YAML 00036464
                           JSON::XS 00070104
                 Devel::EvalContext 00075048
                     Term::ReadLine 00079656
                  Text::SimpleTable 00088048
                      HTTP::Session 00098288
                        MIME::Types 00115000
              Log::Dispatch::Config 00139528
                              Error 00158112
                            Kwalify 00166184
                      Error::Simple 00166488
          Locale::Maketext::Extract 00306040
           Locale::Maketext::Simple 00307360
                      Sub::Exporter 00320272
                      FindBin::libs 00424320
                           App::CLI 00505976
          Module::Pluggable::Object 00539656
                              Mouse 00634128
                   File::Find::Rule 00646984
                           Template 00860216
                        Path::Class 01099304
                  Pod::Simple::Text 01103248
                       HTTP::Engine 01738008
                      Module::Setup 05867920
                       HTTP::Router 07199320

HTTP::Routerがメモリをくってるのは現状の版がMooseだからで、これは将来的にMouseに置き換えれば数Mbは削減できるはず。

こうみると、Path::Classが若干メモリ食い過ぎな感じ。あとはエンジンコアで使ってない物が多いからそれほど問題にならなそうかな。