如何使PSGI程序每个进程只进行一次昂贵的初始化,而不是每个线程?

时间:2017-05-30 08:44:49

标签: multithreading perl psgi

交叉发布:http://perlmonks.org/?node_id=1191821

考虑app.psgi

#!perl
use 5.024;
use strictures;
use Time::HiRes qw(sleep);

sub mock_connect {
    my $how_long_it_takes = 3 + rand;
    sleep $how_long_it_takes;
    return $how_long_it_takes;
}
sub main {
    state $db_handle = mock_connect($dsn);
    return sub { [200, [], ["connect took $db_handle seconds\n"]] };
}
my $dsn = 'dbi:blahblah'; # from config file
my $app = main($dsn);

衡量plackupHTTP::Server::PSGI: Accepting connections at http://0:5000/):

› perl -MBenchmark=timeit,timestr,:hireswallclock -E"say timestr timeit 10, sub { system q(curl http://localhost:5000) }"
connect took 3.0299610154043 seconds
connect took 3.0299610154043 seconds
connect took 3.0299610154043 seconds
connect took 3.0299610154043 seconds
connect took 3.0299610154043 seconds
connect took 3.0299610154043 seconds
connect took 3.0299610154043 seconds
connect took 3.0299610154043 seconds
connect took 3.0299610154043 seconds
connect took 3.0299610154043 seconds
2.93921 wallclock secs ( 0.03 usr +  0.06 sys =  0.09 CPU) @ 107.53/s (n=10)

衡量thrallStarting Thrall/0.0305 (MSWin32) http server listening at port 5000):

› perl -MBenchmark=timeit,timestr,:hireswallclock -E"say timestr timeit 10, sub { system q(curl http://localhost:5000) }"
connect took 3.77111188120125 seconds
connect took 3.15455510265111 seconds
connect took 3.77111188120125 seconds
connect took 3.15455510265111 seconds
connect took 3.77111188120125 seconds
connect took 3.64333342488772 seconds
connect took 3.15455510265111 seconds
connect took 3.77111188120125 seconds
connect took 3.85268922343767 seconds
connect took 3.64333342488772 seconds
17.4764 wallclock secs ( 0.02 usr +  0.09 sys =  0.11 CPU) @ 90.91/s (n=10)

这种性能是不可接受的,因为尽管state变量,初始化仍会发生几次。你是如何做到这一点只发生一次?

2 个答案:

答案 0 :(得分:1)

无论出于何种原因,程序thrall在其配置部分中对“ loader”参数进行了硬编码:

my $runner = Plack::Runner->new(
    server     => 'Thrall',
    env        => 'deployment',
    loader     => 'Delayed',
    version_cb => \&version,
);

$runner->parse_options(@ARGV);

该字符串"Delayed"指向模块Plack::Loader::Delayed,该模块将延迟加载.psgi文件,直到出现第一个请求。那将符合您的基准测试结果。 (如果您再次运行基准测试而又没有杀死Thrall,您将看到相同的输出)。

您可以尝试运行thrall -L +Plack::Loader app.psgi,该操作会将“ loader”参数恢复为硬编码在Plack::Runner中的默认值。

答案 1 :(得分:-1)

这不是Starman--preload-app选项吗?