Perl 7 功能要求:類型語彙的密封子
.
問題
Perl 5 的 OO 程式實際執行方法查詢效能超載比直接、具名子常式呼叫多出 50%
最初的解決方案:Doug MacEachern 的方法查詢最佳化
Doug 是 mod_perl 專案的創作者,回歸 90s 中期,因此顯然撰寫了高效能 Perl 的作品。他的許多貢獻之一p5p 使用方法 + 將 OO 方法查詢超載的效能降低一半@ISA
階層快取,可查尋 mod_perl 物件 (例如) 的執行時期物件方法Apache2::RequestRec
這不是處理來電的問題C 結構
get-set 存取子方法— 許多 mod_perl API 的常見情況。Perl 在 httpd 的程式實際執行方法呼叫查尋罰款結構 request_rec *
,mod_perl 會透過下列方式公開:Apache2::RequestRec
什麼Doug 正在尋找.
指標指令碼.
#!/usr/bin/env -S perl -Ilib -Iblib/arch
use Test::More tests => 3;
use POSIX 'dup2';
dup2 fileno(STDERR), fileno(STDOUT);
use strict;
use warnings;
use Benchmark ':all';
our ($x, $z);
$x = bless {}, "Foo";
$z = Foo->can("foo");
sub method {$x->foo}
sub class {Foo->foo}
sub anon {$z->($x)}
sub bar { 1 }
sub reentrant;
BEGIN {
package Foo;
use base 'sealed';
use sealed 'deparse';
sub foo { shift }
my $n;
sub _foo :Sealed { my main $x = shift; $n++ ? $x->bar : $x->reentrant }
}
sub func {Foo::foo($x)}
BEGIN {our @ISA=qw/Foo/}
use sealed 'deparse';
my main $y; #sealed src filter transforms this into: my main $y = 'main';
sub sealed :Sealed {
$y->foo();
}
sub also_sealed :Sealed {
my main $a = shift;
if ($a) {
my Benchmark $bench;
my $inner = $a;
return sub :Sealed {
my Foo $b = $a;
$inner->foo($b->foo($inner->bar, $inner, $bench->cmpthese));
$a = $inner;
$a->foo;
$b->bar; # error!
};
}
$a->bar();
}
sub reentrant :Sealed { my main $b = shift; local our @Q=1; my $c = $b->_foo }
ok($y->reentrant()==1);
my %tests = (
func => \&func,
method => \&method,
sealed => \&sealed,
class => \&class,
anon => \&anon,
);
cmpthese 20_000_000, \%tests;
ok(1);
use constant LOOPS => 3;
sub method2 {
my $obj = "main";
for (1..LOOPS) {
$obj->foo;
$obj->bar;
$obj->reentrant;
}
}
sub sealed2 :Sealed {
my main $obj; # sealed-src-filter
for (1..LOOPS) {
$obj->foo;
$obj->bar;
$obj->reentrant;
}
}
cmpthese 1_000_000, {
method => \&method2,
sealed => \&sealed2,
};
ok(1);
基準結果
1..3
sealed: compiling main->reentrant lookup.
sealed: compiling main->bar lookup.
sub _foo :sealed {
package Foo;
use warnings;
use strict;
my main $x = shift();
$n++ ? $x->bar:compiled : $x->reentrant:compiled;
}
sealed: compiling main->foo lookup.
sub sealed :sealed {
use warnings;
use strict;
$y->foo:compiled;
}
sealed: compiling Benchmark->cmpthese lookup.
sealed: compiling Foo->foo lookup.
sealed: compiling main->foo lookup.
sealed: compiling Foo->bar lookup.
sealed: tweak() aborted: sealed: invalid lookup: Foo->bar - did you forget to 'use Foo' first?
sub __ANON__ :sealed {
use warnings;
use strict;
my Foo $b = $a;
$inner->foo($b->foo:compiled($inner->bar, $inner, $bench->cmpthese:compiled));
$a = $inner;
$a->foo:compiled;
$b->bar;
}
sealed: compiling main->bar lookup.
sub also_sealed :sealed {
use warnings;
use strict;
my main $a = shift();
if ($a) {
my Benchmark $bench = 'Benchmark';
my $inner = $a;
return sub {
my Foo $b = $a;
$inner->foo($b->foo:compiled($inner->bar, $inner, $bench->cmpthese:compiled));
$a = $inner;
$a->foo:compiled;
$b->bar;
}
;
}
$a->bar:compiled;
}
sealed: compiling main->_foo lookup.
sub reentrant :sealed {
use warnings;
use strict;
my main $b = shift();
(local our(@Q)) = 1;
my $c = $b->_foo:compiled;
}
sealed: compiling main->foo lookup.
sealed: compiling main->bar lookup.
sealed: compiling main->reentrant lookup.
sub sealed2 :sealed {
use warnings;
use strict;
my main $obj = 'main';
foreach $_ (1 .. 3) {
$obj->foo:compiled;
$obj->bar:compiled;
$obj->reentrant:compiled;
}
}
ok 1
Rate class method anon func sealed
class 16129032/s -- -4% -26% -33% -36%
method 16806723/s 4% -- -23% -30% -34%
anon 21739130/s 35% 29% -- -10% -14%
func 24096386/s 49% 43% 11% -- -5%
sealed 25316456/s 57% 51% 16% 5% --
ok 2
Rate method sealed
method 546448/s -- -17%
sealed 662252/s 21% --
ok 3
建議的 Perl 7 解決方案::密封
範例程式碼:
use v7.0;
use Apache2::RequestRec;
sub handler :sealed {
my Apache2::RequestRec $r = shift;
$r->content_type("text/html"); #compile time method lookup
}
Production-Quality,Robust Perl v5.28+ 原型:sealed.pm v7.0.7
您可以在下列位置取得 perl 5.30+ 的編譯指示:sealed.pm
Pod 應執行 mod_perl2 (含執行緒) 和 httpd-2.4 (含事件 mpm),而不是以 any 比例執行 segfault。測試日期第 11.4 期
以及烏本土 22.04
好玩,試試看單鍵修補 終止ModPerl::RegistryCooker
<VirtualHost *:443>
PerlModule ModPerl::RegistryCookerSealed
PerlResponseHandler ModPerl::Registry
AddHandler perl-script .pl
Options +ExecCGI
</VirtualHost>
它會啟用其效果子處理程式 :密封的 {script here}
在您所有的ModPerl::登錄
script,類似此項目.
~/src/cms% h2load -n 100000 -c 1000 -m 100 -t 10 http://localhost/perl-script/enquiry.pl\?lang=.es
starting benchmark...
spawning thread #0: 100 total client(s). 10000 total requests
spawning thread #1: 100 total client(s). 10000 total requests
spawning thread #2: 100 total client(s). 10000 total requests
spawning thread #3: 100 total client(s). 10000 total requests
spawning thread #4: 100 total client(s). 10000 total requests
spawning thread #5: 100 total client(s). 10000 total requests
spawning thread #6: 100 total client(s). 10000 total requests
spawning thread #7: 100 total client(s). 10000 total requests
spawning thread #8: 100 total client(s). 10000 total requests
spawning thread #9: 100 total client(s). 10000 total requests
Application protocol: h2c
progress: 10% done
progress: 20% done
progress: 30% done
progress: 40% done
progress: 50% done
progress: 60% done
progress: 70% done
progress: 80% done
progress: 90% done
progress: 100% done
finished in 13.07s, 7652.14 req/s, 11.83MB/s
requests: 100000 total, 100000 started, 100000 done, 100000 succeeded, 0 failed, 0 errored, 0 timeout
status codes: 100000 2xx, 0 3xx, 0 4xx, 0 5xx
traffic: 154.61MB (162119955) total, 566.39KB (579980) headers (space savings 95.47%), 152.30MB (159700000) data
min max mean sd +/- sd
time for request: 5.74ms 12.77s 6.39s 3.61s 58.14%
time for connect: 304us 293.01ms 70.17ms 76.83ms 74.80%
time to 1st byte: 7.86ms 7.87s 3.33s 1.82s 50.40%
req/s : 7.71 248.17 19.60 28.07 92.70%
請參閱https://github.com/SunStarSys/sealed/blob/master/lib/sealed.pm。尋找t/bench.pl
這將允許 Perl 5 執行範例代碼content_type