Skip to content

Binary search performance regressed in 1.25 #53823

Closed

Description

@Emerentius

The speedup obtained by the optimizations from #45333 which hit stable in 1.23 were mostly lost again from 1.25 onwards, because the compiler started emitting a branch instead of a cmov.

1.24

14  cmp     qword ptr [rsi + 8*rax], rcx
15  cmova   rax, r8

1.25

18  cmp     qword ptr [rsi + 8*r9], rcx
19  ja      .LBB0_7
20  mov     r8, r9
21  .LBB0_7:

From godbolt: https://godbolt.org/z/DUDl-T

Bench comparison with 1.23 nightly (2017-11-20, 9 days after PR merge)

 name                        old_1.23 ns/iter  new_1.23 ns/iter  diff ns/iter   diff %  speedup 
 binary_search_l1            70                28                         -42  -60.00%   x 2.50 
 binary_search_l1_with_dups  46                28                         -18  -39.13%   x 1.64 
 binary_search_l2            94                42                         -52  -55.32%   x 2.24 
 binary_search_l2_with_dups  68                42                         -26  -38.24%   x 1.62 
 binary_search_l3            267               234                        -33  -12.36%   x 1.14 
 binary_search_l3_with_dups  198               236                         38   19.19%   x 0.84 

and status quo with 1.30 nightly (2018-08-15)

 name                        old_1.30 ns/iter  new_1.30 ns/iter  diff ns/iter   diff %  speedup 
 binary_search_l1            75                68                          -7   -9.33%   x 1.10 
 binary_search_l1_with_dups  46                61                          15   32.61%   x 0.75 
 binary_search_l2            99                89                         -10  -10.10%   x 1.11 
 binary_search_l2_with_dups  71                89                          18   25.35%   x 0.80 
 binary_search_l3            272               245                        -27   -9.93%   x 1.11 
 binary_search_l3_with_dups  212               256                         44   20.75%   x 0.83 

Activity

  1. added
    I-slowIssue: Problems and improvements with respect to performance of generated code.
    on Aug 30, 2018
  2. Emerentius commented on Aug 31, 2018

    @Emerentius
    ContributorAuthor

    The likely culprit is the upgrade from LLVM 4 to 6. The upgrade was merged on the 10th of Feb. The binary search was fast on the 9th and slow on the 12th.

    @estebank The optimization did hit stable (if only for 2 releases), so does it not need the regression-from-stable-to-stable label?

  3. estebank commented on Aug 31, 2018

    @estebank
    Contributor

    @Emerentius what do you mean for only 2 releases? Isn't the slowdown present in stable through nightly? Reading the assembly from godbolt it seems to me like there have been some changes but the code causing the slowdown presented in this issue is still there. If that is the case, then it would need that label, but if it was fixed in current stable, then we can close the ticket, as I do not believe we cut point releases for previous stable releases.

  4. Emerentius commented on Aug 31, 2018

    @Emerentius
    ContributorAuthor

    @estebank I mean it was fast in 1.23 stable and slow from 1.25 stable on, so fast for 2 stable releases, then regressed.

  5. self-assigned this
    on Nov 29, 2018
  6. pnkfelix commented on Nov 29, 2018

    @pnkfelix
    Contributor

    triage: P-medium, since I don't think investigating this takes priority over other things currently being juggled. but also self-assigning since I'm curious and I think I can do some bisection as a background task, assuming I can reproduce the perf regression locally.

  7. pnkfelix commented on Nov 29, 2018

    @pnkfelix
    Contributor

    discussed in T-compiler meeting. Re-prioritizing as P-high just for evaluating the scope of the regression (though some good work on that is already evident in this comment thread).

  8. added
    P-highHigh priority
    and removed
    I-slowIssue: Problems and improvements with respect to performance of generated code.
    on Nov 29, 2018
  9. pnkfelix commented on Dec 12, 2018

    @pnkfelix
    Contributor

    Not sure why I previously removed I-slow; I'm putting it back now.

  10. added
    I-slowIssue: Problems and improvements with respect to performance of generated code.
    on Dec 12, 2018
  11. pnkfelix commented on Dec 12, 2018

    @pnkfelix
    Contributor

    Hey @Emerentius, what is the distinction you are making in the columns with the prefix "old_" and "new_" in the tables you present?

    That is, I would have thought that "old_" somehow corresponds to the state prior to the changes from PR #45333 and "new_" corresponds to after PR #45333 landed; but you already established that PR #45333 landed in between the two versions that each have "old_" and "new_" labels applied to them.

    So I don't understand what difference has been applied to either the code or the benchmark in between the two columns there. (Hypothesis: Is "old_" testing the binary search implementation prior to PR #45333, and "new_" testing the binary search implementation that was added by PR #45333 ?)

  12. pnkfelix commented on Dec 12, 2018

    @pnkfelix
    Contributor

    (In any case I definitely am able to reproduce a regression on my Linux desktop on benches/slice between nightly-2018-02-09 and 2018-02-12, as anticipated/noted by #53823 (comment) ; there's a fair amount of noise between runs when looking at binary_search_l3 in my own machine, but binary_search_l1 is much more consistent in illustrating a 2x regression for me.)

  13. Emerentius commented on Dec 12, 2018

    @Emerentius
    ContributorAuthor

    @pnkfelix

    Hypothesis: Is "old_" testing the binary search implementation prior to PR #45333, and "new_" testing the binary search implementation that was added by PR #45333 ?

    That is exactly it

  14. 34 remaining items

  15. yaahc commented on Jul 22, 2021

    @yaahc
    Member

    What Josh said, I've gone ahead and removed the T-libs label, thanks for the confirmation @pnkfelix ^_^.

  16. vlovich commented on Sep 1, 2023

    @vlovich

    Could something like https://docs.rs/cmov/latest/cmov/ be used in the interim to force the usage of cmov to recover the performance?

  17. mohe2015 commented on Sep 1, 2023

    @mohe2015
    Contributor

    Is profile guided optimization able to do anything in this case maybe?

  18. nikic commented on Sep 14, 2023

    @nikic
    Contributor

    The x86 backend should now respect __builtin_unpredicate for cmov conversion, so if we can expose that in rustc in some way, we can use that.

  19. the8472 commented on Sep 14, 2023

    @the8472
    Member

    There's a discussion what to do about likely()/unlikely() on IRLO. Adding an unpredictable() was mentioned too.

  20. added a commit that references this issue on Jul 26, 2024
    d000d5f
  21. Amanieu commented on Jul 26, 2024

    @Amanieu
    Member

    See #128254 for a potential fix.

  22. added 5 commits that reference this issue on Jul 26, 2024
    627c57f
    7751cfe
    21ee157
    f3a8465
    bb58488
  23. added 2 commits that reference this issue on Jul 30, 2024
    5e89635
    1932602
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-LLVMArea: Code generation parts specific to LLVM. Both correctness bugs and optimization-related issues.I-slowIssue: Problems and improvements with respect to performance of generated code.P-lowLow priorityT-compilerRelevant to the compiler team, which will review and decide on the PR/issue.regression-from-stable-to-stablePerformance or correctness regression from one stable version to another.

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions