On Thu, 24 Sep 2026 18:11:09 GMT, Andrew Haley <[email protected]> wrote:

>> Please use [this 
>> link](https://github.com/openjdk/jdk/pull/28541/changes?w=1) to view the 
>> files changed.
>> 
>> Profile counters scale very badly.
>> 
>> The overhead for profiled code isn't too bad with one thread, but as the 
>> thread count increases, things go wrong very quickly.
>> 
>> For example, here's a benchmark from the OpenJDK test suite, run at 
>> TieredLevel 3 with one thread, then three threads:
>> 
>> 
>> Benchmark (randomized) Mode Cnt Score Error Units
>> InterfaceCalls.test2ndInt5Types false avgt 4 27.468 ± 2.631 ns/op
>> InterfaceCalls.test2ndInt5Types false avgt 4 240.010 ± 6.329 ns/op
>> 
>> 
>> This slowdown is caused by high memory contention on the profile counters. 
>> Not only is this slow, but it can also lose profile counts.
>> 
>> This patch is for C1 only. It'd be easy to randomize C1 counters as well in 
>> another PR, if anyone thinks it's worth doing.
>> 
>> One other thing to note is that randomized profile counters degrade very 
>> badly with small decimation ratios. For example, using a ratio of 2 with 
>> `-XX:ProfileCaptureRatio=2` with a single thread results in
>> 
>> 
>> Benchmark                        (randomized)  Mode  Cnt   Score   Error  
>> Units
>> InterfaceCalls.test2ndInt5Types         false  avgt    4  80.147 ± 9.991  
>> ns/op
>> 
>> 
>> The problem is that the branch prediction rate drops away very badly, 
>> leading to many mispredictions. It only really makes sense to use higher 
>> decimation ratios, e.g. 64.
>> 
>> ---------
>> - [x] I confirm that I make this contribution in accordance with the 
>> [OpenJDK Interim AI Policy](https://openjdk.org/legal/ai).
>
> Andrew Haley has updated the pull request with a new target base due to a 
> merge or a rebase. The pull request now contains 215 commits:
> 
>  - Merge from master
>  - Better
>  - Crud
>  - Merge zarquon:/local/theRealAph-jdk into JDK-8134940
>  - Cleanup
>  - Cleanup
>  - Revert "More"
>    
>    This reverts commit 3011e0fa6ef761ed7bb498a314b741b1d2f1bd90.
>  - Revert "Hacks to estimate profiling overhead."
>    
>    This reverts commit 4e2fdc2134a8057ad91e23642f66dc6a5728dce7.
>  - Hacks to estimate profiling overhead.
>  - More
>  - ... and 205 more: https://git.openjdk.org/jdk/compare/4be9a676...19eddaf2

These results look a lot more predictable.

The reason for increased uncommon traps at lower capture ratios is that the 
overheads of profiling lead C1-compiled code to run more slowly, just because 
they're executing more instructions. At higher ratios it levels out, but 
increases again as C2 is fed with increasingly inaccurate data.

I'm not certain as to the cause of the somewhat worse performance figures when 
the ratio is a more reasonable 64-128. It may be a simple matter of tuning: I 
note that with capture ratio = 1 (i.e. normal) a huge number of methods are 
compiled at Tier 2, and this barely happens with any capture ratio > 1. I have 
no idea what is causing this, but it looks significant.

As this is an experimental patch, perhaps this could be investigated later.


fedora:scratch $ sh  ./run-renaissance.sh.1 dotty -r 20
dotty -r 20

--- Patched, PCR=1
Run 1: 4716 1465 1022 878 773 684 609 593 541 524 511 486 459 455 440 435 439 
449 422 425 
Run 2: 4750 1547 1056 860 745 666 619 572 560 517 506 495 472 472 464 423 425 
426 424 437 
Run 3: 4692 1496 1024 854 766 660 609 589 542 526 500 483 462 447 457 423 429 
454 414 399 

Tier1: 0.072 s, 9818 bytes, 2150 methods;
Tier2: 2.139 s, 1013292 bytes, 5280 methods;
Tier3: 8.380 s, 2514244 bytes, 13530 methods;
Tier4: 45.351 s, 6130314 bytes, 6510 methods;

Uncommon traps hit: 459


--- Patched, PCR=4
Run 1: 5600 1969 1281 985 833 756 717 685 642 631 611 608 583 573 572 561 542 
559 540 540 
Run 2: 5564 1914 1278 983 817 755 693 681 639 629 610 619 586 589 571 561 550 
551 540 535 
Run 3: 5594 1972 1291 1005 843 754 703 682 650 623 625 614 606 572 567 553 558 
557 547 526 

Tier1: 0.065 s, 9733 bytes, 2131 methods;
Tier2: 0.181 s, 91461 bytes, 344 methods;
Tier3: 8.684 s, 2717037 bytes, 16105 methods;
Tier4: 36.642 s, 5319785 bytes, 8303 methods;

Uncommon traps hit: 579


--- Patched, PCR=16
Run 1: 5139 1793 1250 936 798 733 660 630 608 592 582 585 563 552 546 543 527 
533 517 506 
Run 2: 5004 1769 1186 937 807 731 678 655 639 608 587 588 572 557 557 542 531 
533 530 531 
Run 3: 5071 1731 1206 939 812 734 662 627 631 586 574 598 560 565 554 554 564 
534 530 510 

Tier1: 0.063 s, 9751 bytes, 2137 methods;
Tier2: 0.228 s, 129309 bytes, 545 methods;
Tier3: 8.565 s, 2713460 bytes, 16066 methods;
Tier4: 36.063 s, 5103268 bytes, 8085 methods;

Uncommon traps hit: 535


--- Patched, PCR=64
Run 1: 4751 1700 1217 920 796 714 660 605 583 563 546 548 537 524 515 516 502 
490 495 487 
Run 2: 4806 1686 1130 886 769 696 644 634 583 570 562 556 535 541 526 538 524 
524 510 512 
Run 3: 4794 1638 1136 922 770 694 652 588 565 570 544 551 533 516 529 508 506 
496 497 480 

Tier1: 0.072 s, 9745 bytes, 2135 methods;
Tier2: 0.375 s, 230407 bytes, 987 methods;
Tier3: 8.585 s, 2695910 bytes, 15918 methods;
Tier4: 35.684 s, 5050715 bytes, 7703 methods;

Uncommon traps hit: 518

--- Patched, PCR=128
Run 1: 4719 1626 1120 894 762 678 631 599 561 531 524 525 508 522 496 488 475 
467 469 468 
Run 2: 4625 1593 1149 911 762 680 619 576 576 560 519 519 507 508 490 484 495 
469 470 477 
Run 3: 4786 1606 1114 867 737 651 604 591 552 531 526 527 523 497 494 486 485 
497 474 458 

Tier1: 0.070 s, 9756 bytes, 2138 methods;
Tier2: 0.455 s, 288069 bytes, 1445 methods;
Tier3: 8.476 s, 2695056 bytes, 15765 methods;
Tier4: 35.774 s, 5112199 bytes, 7412 methods;

Uncommon traps hit: 523

--- Patched, PCR=256
Run 1: 4709 1655 1149 881 751 676 621 577 538 549 513 505 494 490 497 487 470 
470 464 475 
Run 2: 4584 1511 1076 840 741 672 611 584 545 536 528 502 530 499 479 482 489 
471 462 465 
Run 3: 4517 1537 1114 865 766 669 612 587 553 527 530 501 507 486 484 485 468 
482 490 481 

Tier1: 0.066 s, 9789 bytes, 2143 methods;
Tier2: 0.633 s, 320269 bytes, 1734 methods;
Tier3: 8.562 s, 2684664 bytes, 15659 methods;
Tier4: 36.094 s, 5165114 bytes, 7352 methods;

Uncommon traps hit: 531


--- Patched, PCR=1024
Run 1: 4631 1637 1141 891 753 673 621 586 542 551 520 511 489 495 486 493 476 
464 464 453 
Run 2: 4646 1522 1098 875 735 682 610 559 534 523 501 493 486 480 469 473 461 
453 460 473 
Run 3: 4619 1544 1133 877 752 661 613 556 538 536 495 488 495 476 470 471 456 
459 450 453 

Tier1: 0.069 s, 9774 bytes, 2141 methods;
Tier2: 0.820 s, 420536 bytes, 1912 methods;
Tier3: 8.401 s, 2653668 bytes, 15504 methods;
Tier4: 38.971 s, 5263978 bytes, 7524 methods;

Uncommon traps hit: 539


--- Patched, PCR=4096
Run 1: 4486 1605 1129 915 774 668 638 592 565 531 518 523 504 494 498 480 497 
465 464 457 
Run 2: 4830 1547 1060 884 755 634 628 582 549 536 515 507 487 495 486 493 469 
466 464 455 
Run 3: 4703 1628 1170 943 818 706 639 596 565 542 516 529 496 483 475 493 469 
461 475 453 

Tier1: 0.066 s, 9758 bytes, 2140 methods;
Tier2: 1.117 s, 575443 bytes, 2738 methods;
Tier3: 8.045 s, 2554912 bytes, 14804 methods;
Tier4: 37.619 s, 4888283 bytes, 6976 methods;

Uncommon traps hit: 528


--- Patched, PCR=16384
Run 1: 4336 1474 1065 880 784 723 691 664 619 610 596 577 555 557 551 529 540 
517 520 491 
Run 2: 4475 1513 1131 913 812 742 695 636 601 623 577 579 546 553 540 531 533 
513 518 505 
Run 3: 4380 1485 1103 941 768 708 698 658 622 589 583 572 554 538 533 539 519 
528 511 508 

Tier1: 0.067 s, 9849 bytes, 2161 methods;
Tier2: 1.359 s, 792786 bytes, 4410 methods;
Tier3: 7.497 s, 2349698 bytes, 13160 methods;
Tier4: 32.239 s, 3999967 bytes, 8150 methods;

Uncommon traps hit: 1041


--- Patched, PCR=65536
Run 1: 4567 1812 1477 1125 1058 982 911 851 815 818 790 750 723 730 691 686 662 
680 655 652 
Run 2: 4594 1881 1399 1135 1050 961 931 866 843 807 792 752 740 737 714 711 684 
670 677 661 
Run 3: 4635 1886 1446 1190 1134 1003 970 888 848 813 782 771 741 727 720 715 
691 685 664 653 

Tier1: 0.084 s, 9791 bytes, 2148 methods;
Tier2: 0.301 s, 153499 bytes, 1011 methods;
Tier3: 8.450 s, 2543573 bytes, 14980 methods;
Tier4: 30.574 s, 3681626 bytes, 7863 methods;

Uncommon traps hit: 1225

Some interesting ideas there.

The jump to the slow stub should be executed rarely, so the fast path is small. 
It is this:
`cmp $0x40000000,%r14d; jb stub; xor %ebx,%ebx; crc32 %ebx,%r14d` However, in 
the cases where a counter is zero at code generation time (about 50% of static 
cases, presumably far less for dynamic execution) we have to insert a lot more 
code. In that case it might be worthwhile inserting the rest inline, but I 
suspect that's the rare case.

As for the x86 microarch stuff, OK, but I doubt that's it. I've been mostly 
testing on AArch64, where I see similar behaviour.

I've added a flag, `AggressiveProfileReduction`.

With this flag, counters whose values are unknown at compiler time are treated 
differently. By default, we don't do profile decimation at all. When 
`AggressiveProfileReduction` is on, we emit a 0->1 test in these cases and then 
proceed to test and step the RNG.

When a counter is zero at compile time, we just increment the counter, 
regardless of `ProfileCaptureRatio`.

With these changes, single-threaded performance is neutral with 
`ProfileCaptureRatio` set to something reasonable such as 64 or 128. 
Multi-threaded performance is better, but not quite as good as with 
`AggressiveProfileReduction`. I think this is a reasonable compromise.

I haven't yet touched Arm A32.

-------------

PR Comment: https://git.openjdk.org/jdk/pull/28541#issuecomment-5835566894
PR Comment: https://git.openjdk.org/jdk/pull/28541#issuecomment-5875576488
PR Comment: https://git.openjdk.org/jdk/pull/28541#issuecomment-5955374387

Reply via email to