Skip to content

Conversation

@richardleach
Copy link
Contributor

@richardleach richardleach commented Aug 3, 2022

This commit introduces a new OP to replace cases of OP_ANONLIST and
OP_ANONHASH where there are zero elements, which is very common in
Perl code.

As an example, my $x = {} is currently implemented like this:

...
6     <2> sassign vKS/2 ->7
4        <@> anonhash sK* ->5
3           <0> pushmark s ->4
5        <0> padsv[$x:1,2] sRM*/LVINTRO ->6

The pushmark serves no meaningful purpose when there are zero
elements and the anonhash, besides undoing the pushmark,
performs work that is unnecessary for this special case.

The peephole optimizer transforms this example into:

...
5     <2> sassign vKS/2 ->6
3        <@> anonavhv_mt_rv sK*/ANONHASH ->4
-           <0> ex-pushmark s ->3
4        <0> padsv[$x:1,2] sRM*/LVINTRO ->5

The following toy code shows the op-related speedup:
for (0 .. 100_000_000) { {} }

With blead:

          3,485.86 msec task-clock                #    0.996 CPUs utilized          
                10      context-switches          #    0.003 K/sec                  
                 0      cpu-migrations            #    0.000 K/sec                  
               199      page-faults               #    0.057 K/sec                  
    15,571,616,464      cycles                    #    4.467 GHz                    
        22,684,235      stalled-cycles-frontend   #    0.15% frontend cycles idle   
             5,861      stalled-cycles-backend    #    0.00% backend cycles idle    
    59,605,663,770      instructions              #    3.83  insn per cycle         
                                                  #    0.00  stalled cycles per insn
    13,601,121,374      branches                  # 3901.795 M/sec 

Patched:

          3,031.49 msec task-clock                #    1.000 CPUs utilized          
                 9      context-switches          #    0.003 K/sec                  
                 0      cpu-migrations            #    0.000 K/sec                  
               198      page-faults               #    0.065 K/sec                  
    13,499,894,113      cycles                    #    4.453 GHz                    
         8,209,347      stalled-cycles-frontend   #    0.06% frontend cycles idle   
             5,279      stalled-cycles-backend    #    0.00% backend cycles idle    
    50,605,323,929      instructions              #    3.75  insn per cycle         
                                                  #    0.00  stalled cycles per insn
    11,601,055,120      branches                  # 3826.844 M/sec 

@richardleach
Copy link
Contributor Author

Comments:

  1. I know the new op name is crufty. Suggestions welcome.
  2. I wasn't sure how often the non-OPf_SPECIAL case of ANONHASH and ANONLIST comes up (B::Deparse certainly doesn't expect to see it), so just ignored it for this optimization. If that's unhelpful, please let me know (with code examples, please).

@richardleach richardleach force-pushed the hydahy/ANONLISTHASH_EMPTY branch from fb6b801 to 61dfc3f Compare August 3, 2022 23:51
@iabyn
Copy link
Contributor

iabyn commented Aug 4, 2022 via email

@iabyn
Copy link
Contributor

iabyn commented Aug 4, 2022 via email

@richardleach richardleach force-pushed the hydahy/ANONLISTHASH_EMPTY branch 3 times, most recently from 8f0b0aa to 9764573 Compare August 5, 2022 20:04
@richardleach
Copy link
Contributor Author

Thanks for the helpful comments, @iabyn. Think I've actioned all of them, apart from running bench.pl, which I'll do once the pp_ function is finalised.

Besides a general re-review, two specific new things I'd appreciate you taking a look at

  • I wasn't sure how concise "coerce rv to be RV-capable" can safely be. The current code passes all tests, but...that doesn't mean it's okay.
  • I haven't figured out how to do without the mortal RV (refsv in pp_emptyavhv) when doing a lexical assignment, since leaving it out causes a leakage in t/op/svleak.t.

@richardleach richardleach changed the title OP_ANONAVHV_MT_RV - optimized empty ANONLIST/ANONHASH OP_EMPTYAVHV - optimized empty ANONLIST/ANONHASH Aug 7, 2022
@richardleach richardleach force-pushed the hydahy/ANONLISTHASH_EMPTY branch from 9764573 to 094764e Compare August 7, 2022 22:52
@iabyn
Copy link
Contributor

iabyn commented Aug 8, 2022 via email

@richardleach
Copy link
Contributor Author

Thanks for the updated comments. I'll try to do an updated push later this week.
FWIW, the test in t/op/svleak.t which fails if the refsv mortal isn't created is this one:

{ # broken by 304474c3, fixed by cefd5c7c, but didn't seem to cause
  # any other test failures
  # base test case from ribasushi (Peter Rabbitson)
  no warnings 'experimental::builtin';
  use builtin 'weaken';
  my $weak;
  {
    $weak = my $in = {};
    weaken($weak);
    my $out = { in => $in, in => undef }
  }
  ok(!$weak, "hash referenced weakened SV released");
}

@iabyn
Copy link
Contributor

iabyn commented Aug 9, 2022 via email

@richardleach richardleach force-pushed the hydahy/ANONLISTHASH_EMPTY branch from 80e57a1 to bb3d06f Compare August 9, 2022 20:15
@richardleach
Copy link
Contributor Author

Ok, think I sorted out the reference counting.

t/perf/benchmark differences are as follows:


expr::sassign::anonlist
$x = []

        blead emptyavhv
       ------ ---------
    Ir 100.00    120.31
    Dr 100.00    120.16
    Dw 100.00    119.27
  COND 100.00    111.16
   IND 100.00    125.00

COND_m 100.00    100.00
 IND_m 100.00    125.00

 Ir_m1 100.00    100.00
 Dr_m1 100.00    100.00
 Dw_m1 100.00    100.00

 Ir_mm 100.00    100.00
 Dr_mm 100.00    100.00
 Dw_mm 100.00    100.00

expr::sassign::anonlist_lex
$x = []

        blead emptyavhv
       ------ ---------
    Ir 100.00    120.18
    Dr 100.00    120.14
    Dw 100.00    119.35
  COND 100.00    111.11
   IND 100.00    125.00

COND_m 100.00    100.00
 IND_m 100.00    125.00

 Ir_m1 100.00    100.00
 Dr_m1 100.00    100.00
 Dw_m1 100.00    100.00

 Ir_mm 100.00    100.00
 Dr_mm 100.00    100.00
 Dw_mm 100.00    100.00

expr::sassign::my_anonlist_lex
my $x = []

        blead emptyavhv
       ------ ---------
    Ir 100.00    114.49
    Dr 100.00    115.47
    Dw 100.00    114.88
  COND 100.00    108.60
   IND 100.00    120.00

COND_m 100.00    100.00
 IND_m 100.00    125.00

 Ir_m1 100.00    100.00
 Dr_m1 100.00    100.00
 Dw_m1 100.00    100.00

 Ir_mm 100.00    100.00
 Dr_mm 100.00    100.00
 Dw_mm 100.00    100.00

expr::sassign::anonhash
$x = {}

        blead emptyavhv
       ------ ---------
    Ir 100.00    116.33
    Dr 100.00    115.99
    Dw 100.00    114.36
  COND 100.00    110.38
   IND 100.00    125.00

COND_m 100.00    100.00
 IND_m 100.00    125.00

 Ir_m1 100.00    100.00
 Dr_m1 100.00    100.00
 Dw_m1 100.00    100.00

 Ir_mm 100.00    100.00
 Dr_mm 100.00    100.00
 Dw_mm 100.00    100.00

expr::sassign::anonhash_lex
$x = {}

        blead emptyavhv
       ------ ---------
    Ir 100.00    116.25
    Dr 100.00    115.98
    Dw 100.00    114.41
  COND 100.00    110.34
   IND 100.00    125.00

COND_m 100.00    100.00
 IND_m 100.00    125.00

 Ir_m1 100.00    100.00
 Dr_m1 100.00    100.00
 Dw_m1 100.00    100.00

 Ir_mm 100.00    100.00
 Dr_mm 100.00    100.00
 Dw_mm 100.00    100.00

expr::sassign::my_anonhash_lex
my $x = {}

        blead emptyavhv
       ------ ---------
    Ir 100.00    112.28
    Dr 100.00    112.80
    Dw 100.00    111.51
  COND 100.00    108.33
   IND 100.00    120.00

COND_m 100.00    100.00
 IND_m 100.00    125.00

 Ir_m1 100.00    100.00
 Dr_m1 100.00    100.00
 Dw_m1 100.00    100.00

 Ir_mm 100.00    100.00
 Dr_mm 100.00    100.00
 Dw_mm 100.00    100.00

AVERAGE

        blead emptyavhv
       ------ ---------
    Ir 100.00    116.57
    Dr 100.00    116.70
    Dw 100.00    115.56
  COND 100.00    109.98
   IND 100.00    123.29

COND_m 100.00    100.00
 IND_m 100.00    125.00

 Ir_m1 100.00    100.00
 Dr_m1 100.00    100.00
 Dw_m1 100.00    100.00

 Ir_mm 100.00    100.00
 Dr_mm 100.00    100.00
 Dw_mm 100.00    100.00

@richardleach
Copy link
Contributor Author

@iabyn / @demerphq - any more comments on this one? (Deparse.pm will need a version bump, but I'm saving that until it's definitely ready to go.)

@richardleach
Copy link
Contributor Author

Rebased after #20077 merge.

@richardleach
Copy link
Contributor Author

Rebased after aafefcb merge.

@richardleach
Copy link
Contributor Author

@iabyn / @demerphq - I'll merge this within a few days unless you'd prefer me to hold off for further review.

@demerphq
Copy link
Collaborator

demerphq commented Sep 18, 2022 via email

@richardleach
Copy link
Contributor Author

Unless anyone has objections, I'd like to merge this before the next dev release in just over a week's time.

@richardleach richardleach force-pushed the hydahy/ANONLISTHASH_EMPTY branch 2 times, most recently from a274920 to 525a9e8 Compare October 22, 2022 21:30
@demerphq
Copy link
Collaborator

You need a version bump. It looks ok to me.

@richardleach
Copy link
Contributor Author

Thanks. lib/B/op_private.pm seems to need a bump as part of the v.5.37.5 release, so I'll hold off until that has happened.

@toddr
Copy link
Member

toddr commented Oct 24, 2022

@iabyn / @demerphq - I'll merge this within a few days unless you'd prefer me to hold off for further review.

Apologies @richardleach please rebase and force push to your branch. This should correct the issue.

This commit introduces a new OP to replace cases of OP_ANONLIST and
OP_ANONHASH where there are zero elements, which is very common in
Perl code.

As an example, `my $x = {}` is currently implemented like this:
    ...
    6     <2> sassign vKS/2 ->7
    4        <@> anonhash sK* ->5
    3           <0> pushmark s ->4
    5        <0> padsv[$x:1,2] sRM*/LVINTRO ->6

The pushmark serves no meaningful purpose when there are zero
elements and the anonhash, besides undoing the pushmark,
performs work that is unnecessary for this special case.

The peephole optimizer, which also checks for applicability of a
related TARGMY optimization, transforms this example into:
    ...
    -     <1> ex-sassign vKS/2 ->4
    3        <@> emptyavhv[$x:1,2] vK*/LVINTRO,ANONHASH,TARGMY ->4
    -           <0> ex-pushmark s ->3
    -        <0> ex-padsv sRM*/LVINTRO ->-
@richardleach richardleach force-pushed the hydahy/ANONLISTHASH_EMPTY branch from 525a9e8 to b1b67a3 Compare October 24, 2022 20:59
@richardleach
Copy link
Contributor Author

Thanks @toddr. Merging.

@richardleach richardleach merged commit 8b4768d into Perl:blead Oct 24, 2022
@richardleach richardleach deleted the hydahy/ANONLISTHASH_EMPTY branch October 24, 2022 22:21
@iabyn
Copy link
Contributor

iabyn commented Nov 7, 2022 via email

@richardleach
Copy link
Contributor Author

Sorry, I didn't get round to doing this. In short, lools good, apart from these nits:

Thanks, I've started working on them.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants