Perl 7 Solicitação de Recurso: subs selados para lexicals tipados

[ARQUIVADO] Última atualização por Joe Schaefer em sex, 01 mai 2026    origem
 

solstarapenas

O problema

Perl 5’a pesquisa do método de runtime do OO tem 50% mais sobrecarga de desempenho do que uma chamada de sub-rotina direta e nomeada.

A solução inicial: Doug MacEachern’otimizações de pesquisa do método s

Doug foi o criador do projeto mod_perl em meados do 90s, então, obviamente, escrever Perl de alto desempenho foi sua forté. Uma de suas muitas contribuições para p5p foi cortar a penalidade de desempenho da sobrecarga de pesquisa do método OO pela metade, usando um método + @ISA cache de hierarquia para fazer a pesquisa do método do objeto de runtime para objetos mod_perl, como Apache2::RequestRec o mais simplificado possível. Mas isso só nos leva a meio caminho.

Isto é’t um problema insignificante com chamadas para Estrutura C métodos de acessor get-set — a situação comum com muitas APIs mod_perl. Perl’penalidade de pesquisa de chamada de método de runtime s em httpd’s struct request_rec *, que mod_perl expõe através do Apache2::RequestRec módulo, está na mesma ordem de magnitude da execução completa da chamada. Para sites com suporte mod_perl que fazem milhões de chamadas de método XS por segundo, esse é um desperdício terrível de preciosos ciclos de CPU.

O que Doug estava procurando foi uma maneira de dizer a Perl 5 para realizar a pesquisa de método no tempo de compilação, da maneira que faz com chamadas de sub-rotina nomeadas. Toda vez que Doug tentava, ele batia em obstáculos de natureza social ou técnica. Talvez’É hora de fazer outra passagem nessa ideia com o advento de Perl 7.

Script de benchmark.


Resultados do benchmark

1..3
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;
    }
}
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;
}
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

Solução proposta Perl 7: :selado sub-rotinas para léxicos tipados

Código da amostra:

use v5.38;
use Apache2::RequestRec;

sub handler :Sealed (Apache2::RequestRec $r) {
  $r->content_type("text/html"); #compile time method lookup
}

Protótipo Robusto de Perl v5.28+ de Qualidade de Produção: sealed.pm v8.7.7 (no CPAN).

Instruções de compilação para perl 5.30+ estão disponíveis no sealed.pm você deseja executar mod_perl2 w/ ithreads e httpd-2.4 w/ event mpm, e não segfault em escala qualquer. Testado em Solaris 11.4 e Ubuntu 22.04 em amd64.

Para se divertir, tente isso patch de macaco para ModPerl::RegistryCooker:


Permite os efeitos de sub handler : Lacrado {o script vai aqui} em todos os seus ModPerl::Registro scripts, algo como este.

~/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%

Consulte https://github.com/SunStarSys/sealed/blob/master/lib/sealed.pm. Procurar t/bench.pl no diretório pai.

Isso permitirá que Perl 5 faça o código de amostra’s content_type pesquisa de método no tempo de compilação, sem causar problemas de back-compat ou codificadores de CPAN prejudicados, uma vez que esse recurso teria como alvo os desenvolvedores de aplicativos. Não herdáveis autores do módulo OO.

Esta ideia Perlish é gratuitamente roubada de Dylan. Ler isto para o esforço CPython de mais de uma década atrás.