Как сделать программу PSGI дорогостоящей инициализацией только один раз за процесс, а не за поток?
cross-post: 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);
Измерение plackup
(HTTP::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)
Измерение thrall
(Starting 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
. Как вы это делаете, это происходит только один раз?
Ответы
Ответ 1
По какой-то причине программа thrall
жестко закодировала параметр "загрузчик" в своем разделе конфигурации:
my $runner = Plack::Runner->new(
server => 'Thrall',
env => 'deployment',
loader => 'Delayed',
version_cb => \&version,
);
$runner->parse_options(@ARGV);
Эта строка "Delayed"
относится к модулю Plack::Loader::Delayed
, который задерживает загрузку файлов .psgi до получения первого запроса. Это будет соответствовать вашему результату тестирования. (Если вы снова запустите эталонный тест, не убив рабство, вы увидите идентичный результат).
Вы можете попробовать запустить thrall -L +Plack::Loader app.psgi
, который вернет параметр "загрузчик" к значению по умолчанию, жестко заданному в Plack::Runner
.
Ответ 2
Разве это не вариант --preload-app
для Starman?