Skip to content

Perl_av_extend_guts: initialize elements via Zero() rather than while loop(s) #18072

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Oct 4, 2020

Conversation

richardleach
Copy link
Contributor

This PR has two commits, a tabs-to-spaces commit, followed by a refactoring commit. The latter:

  • Changes the means of fresh array element initialization from the previous per-element loop, below, to the Zero() macro (i.e. memzero/memset)
                while (tmp)
                    ary[--tmp] = NULL;
  • Refactors slightly, such that when a shifted array is unshifted, but also has to be grown, there's only one use of Zero() rather than two.

No change in behaviour is intended, this PR is solely intended to improve performance when large arrays are created or resized.

However, the performance difference will be dependent upon the underlying memset/memzero implementation. It would be great if this PR could get some testing on different platforms in order to see if any show worse performance than before.

Local perf testing
On a Core i5 x86-64 Linux VM:

  • Repeatedly creating a new, small SV* array uses ~7 fewer instructions & ~3 fewer branches per iteration, but there's no discernible wallclock change.
    my @ary; for (1 .. 1_000_000) { @ary = (1); undef @ary; }
  • Repeatedly shifting a small array and pushing to it uses ~6 fewer instructions & ~1 fewer branch per iteration, but again, no discernible wallclock change.
    my @ary = (1,2,3); for (1 .. 1_000_000) { shift @ary; shift @ary; push @ary, (4,5); }
  • Doing things that involve creating many more fresh array elements, such as pre-extending the array, have bigger effects, as would be expected. For the following, the wallclock times were all over the place, but the numbers of instructions and branches were consistent:
    my @ary; for (1 .. 1_000_000) { @ary = (1); $ary[1024] = 1; undef @ary; }

blead:

    11,897,373,171      instructions              #    3.89  insn per cycle         
     3,387,878,697      branches                  # 4147.263 M/sec                  
         2,043,989      branch-misses             #    0.06% of all branches    

patched:

     9,098,175,244      instructions              #    3.54  insn per cycle         
     2,444,838,567      branches                  # 3505.562 M/sec                  
         1,569,350      branch-misses             #    0.06% of all branches 

Questions/scope for additional commit(s)?

  1. Can *maxp can ever be < -1? If it can't, the (UNLIKELY(key < -1)) test could be made an else branch off the if (key > *maxp) { test.

  2. When a shifted array (*allocp != *arrayp) has to be grown:

  • Why is the test for (key > *maxp - 10) and not just a repeat of (key > *maxp) ? Seems like this will cause small arrays to be always be grown, even if there's no actual need.
  • Why is the growth factor newmax = key + *maxp, but for an unshifted array it's newmax = *maxp / 5 ?
  • Why is the Perl_safesysmalloc_size check (where present) skipped?

If shifted arrays were treated the same as unshifted arrays in those regards, it would simplify the function and could reduce unnecessary array growth.

@richardleach richardleach added awaiting review do not merge Don't merge this PR, at least for now labels Aug 20, 2020
@richardleach
Copy link
Contributor Author

The comment about new array initialization is inaccurate (re: stacks) and needs amending, but I don't have time to do that right now.

Copy link
Member

@atoomic atoomic left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM thanks for the benchmark

@richardleach
Copy link
Contributor Author

The comment about new array initialization is inaccurate (re: stacks) and needs amending, but I don't have time to do that right now.

PR comments now updated. (Some other core function(s) initializing the first element to &PL_sv_undef for stacks is what I've gathered from @iabyn, but I don't personally know which function(s) do that.)

@richardleach richardleach removed the do not merge Don't merge this PR, at least for now label Sep 29, 2020
@khwilliamson
Copy link
Contributor

@richardleach what review are you awaiting?

@richardleach
Copy link
Contributor Author

@khw not necessarily waiting for another review, had just left it there for a bit to give people a chance to weigh in on the "Questions/scope for additional commit(s)?". @tonycoz or @iabyn or @nwc10 ?

@khwilliamson khwilliamson merged commit 399fef9 into Perl:blead Oct 4, 2020
@richardleach richardleach deleted the hydahy/avguts_memzero branch October 4, 2020 16:33
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants