Code Monkey home page Code Monkey logo

Comments (10)

casparcwang avatar casparcwang commented on July 28, 2024

您好,感谢反馈这个问题,从现象来看似乎是由于Escape Analysis分析没有将第二次add1的BigDecimal做栈上分配导致的,应该属于C2编译的一个bug,根因还需要进一步分析。

从下面的log可以看到,第一执行的时候add1是能够将里面的BigDecimal aBigDecimal b做栈上分配,而第二次执行funLong时则没有做栈上分配,从而导致性能差距较大。

[root@VM-235-31-centos BigDecimal]# /data/openjdk/jdk/build/linux-x86_64-server-fastdebug/images/jdk/bin/java -XX:+PrintEscapeAnalysis  -XX:+PrintEliminateAllocations Foo

======== Connection graph for  Foo::add1
invocation #0: 2 iterations and 0.000003 sec to build connection graph with 676 nodes and worklist size 21

JavaObject(3) NoEscape(NoEscape) [ 320F 316F [ 235 240 ]]   223  Allocate  ===  213  72  185  8  1 ( 59  58  33  1  1  1  1  78  1  1  10  1  22 ) [[ 224  225  226  233  234  235 ]]  rawptr:NotNull ( int:>=0, java/lang/Object:NotNull *, bool, top, bool ) BigDecimal::valueOf @ bci:20 (line 1293) Foo::add1 @ bci:8 (line 34) !jvms: BigDecimal::valueOf @ bci:20 (line 1293) Foo::add1 @ bci:8 (line 34)
LocalVar(13) [ 223P [ 240 ]]   235  Proj  ===  223  [[ 236  240 ]] #5 !jvms: BigDecimal::valueOf @ bci:20 (line 1293) Foo::add1 @ bci:8 (line 34)
LocalVar(16) [ 235 223P [ 320b 316b ]]   240  CheckCastPP  ===  237  235  [[ 252  252  388  372  333  320  320  316  316 ]]  #java/math/BigDecimal:NotNull:exact *  Oop:java/math/BigDecimal:NotNull:exact * !jvms: BigDecimal::valueOf @ bci:20 (line 1293) Foo::add1 @ bci:8 (line 34)

JavaObject(4) NoEscape(NoEscape) [ 168F 162F [ 73 78 ]]   61  Allocate  ===  48  6  7  8  1 ( 59  58  33  1  1  10  1  1  1  1  10  1  22 ) [[ 62  63  64  71  72  73 ]]  rawptr:NotNull ( int:>=0, java/lang/Object:NotNull *, bool, top, bool ) BigDecimal::valueOf @ bci:20 (line 1293) Foo::add1 @ bci:2 (line 33) !jvms: BigDecimal::valueOf @ bci:20 (line 1293) Foo::add1 @ bci:2 (line 33)
LocalVar(14) [ 61P [ 78 ]]   73  Proj  ===  61  [[ 74  78 ]] #5 !jvms: BigDecimal::valueOf @ bci:20 (line 1293) Foo::add1 @ bci:2 (line 33)
LocalVar(17) [ 73 61P [ 168b 162b ]]   78  CheckCastPP  ===  75  73  [[ 91  91  388  372  252  223  217  183  168  168  162  162 ]]  #java/math/BigDecimal:NotNull:exact *  Oop:java/math/BigDecimal:NotNull:exact * !jvms: BigDecimal::valueOf @ bci:20 (line 1293) Foo::add1 @ bci:2 (line 33)

JavaObject(5) NoEscape(NoEscape) [ 614F 610F [ 529 534 ]]   517  Allocate  ===  507  234  335  8  1 ( 59  58  33  1  1  1  1  1  1  1  1  1  1  1  1  1  1  1  1  1  1  1  1  1  1  1  1  1  1  1  1  448  1  396 ) [[ 518  519  520  527  528  529 ]]  rawptr:NotNull ( int:>=0, java/lang/Object:NotNull *, bool, top, bool ) BigDecimal::valueOf @ bci:20 (line 1293) BigDecimal::add @ bci:20 (line 4973) BigDecimal::add @ bci:18 (line 4980) BigDecimal::add @ bci:38 (line 1381) Foo::add1 @ bci:14 (line 36) !jvms: BigDecimal::valueOf @ bci:20 (line 1293) BigDecimal::add @ bci:20 (line 4973) BigDecimal::add @ bci:18 (line 4980) BigDecimal::add @ bci:38 (line 1381) Foo::add1 @ bci:14 (line 36)
LocalVar(15) [ 517P [ 534 ]]   529  Proj  ===  517  [[ 530  534 ]] #5 !jvms: BigDecimal::valueOf @ bci:20 (line 1293) BigDecimal::add @ bci:20 (line 4973) BigDecimal::add @ bci:18 (line 4980) BigDecimal::add @ bci:38 (line 1381) Foo::add1 @ bci:14 (line 36)
LocalVar(18) [ 529 517P [ 614b 610b ]]   534  CheckCastPP  ===  531  529  [[ 546  546  627  614  614  610  610 ]]  #java/math/BigDecimal:NotNull:exact *  Oop:java/math/BigDecimal:NotNull:exact * !jvms: BigDecimal::valueOf @ bci:20 (line 1293) BigDecimal::add @ bci:20 (line 4973) BigDecimal::add @ bci:18 (line 4980) BigDecimal::add @ bci:38 (line 1381) Foo::add1 @ bci:14 (line 36)

Scalar  534  CheckCastPP  ===  531  529  [[ 546  546  610  614  614  610 ]]  #java/math/BigDecimal:NotNull:exact *,iid=517  Oop:java/math/BigDecimal:NotNull:exact *,iid=517 !jvms: BigDecimal::valueOf @ bci:20 (line 1293) BigDecimal::add @ bci:20 (line 4973) BigDecimal::add @ bci:18 (line 4980) BigDecimal::add @ bci:38 (line 1381) Foo::add1 @ bci:14 (line 36)
++++ Eliminated: 517 Allocate
Scalar  240  CheckCastPP  ===  237  235  [[ 252  252  320  316  316  320 ]]  #java/math/BigDecimal:NotNull:exact *,iid=223  Oop:java/math/BigDecimal:NotNull:exact *,iid=223 !jvms: BigDecimal::valueOf @ bci:20 (line 1293) Foo::add1 @ bci:8 (line 34)
++++ Eliminated: 223 Allocate
Scalar  78  CheckCastPP  ===  75  73  [[ 91  91  168  162  252  168  217  162 ]]  #java/math/BigDecimal:NotNull:exact *,iid=61  Oop:java/math/BigDecimal:NotNull:exact *,iid=61 !jvms: BigDecimal::valueOf @ bci:20 (line 1293) Foo::add1 @ bci:2 (line 33)
++++ Eliminated: 61 Allocate

======== Connection graph for  Foo::funInt
invocation #0: 2 iterations and 0.000004 sec to build connection graph with 792 nodes and worklist size 29

JavaObject(9) NoEscape(NoEscape) [ 713F 709F [ 628 633 ]]   616  Allocate  ===  606  327  434  8  1 ( 147  146  21  1  1  29  1  91  1  1  1  1  1  1  1  1  1  1  1  1  1  1  1  1  1  1  1  1  1  1  1  1  1  1  547  1  495 ) [[ 617  618  619  626  627  628 ]]  rawptr:NotNull ( int:>=0, java/lang/Object:NotNull *, bool, top, bool ) BigDecimal::valueOf @ bci:20 (line 1293) BigDecimal::add @ bci:20 (line 4973) BigDecimal::add @ bci:18 (line 4980) BigDecimal::add @ bci:38 (line 1381) Foo::add1 @ bci:14 (line 36) Foo::funInt @ bci:14 (line 17) !jvms: BigDecimal::valueOf @ bci:20 (line 1293) BigDecimal::add @ bci:20 (line 4973) BigDecimal::add @ bci:18 (line 4980) BigDecimal::add @ bci:38 (line 1381) Foo::add1 @ bci:14 (line 36) Foo::funInt @ bci:14 (line 17)
LocalVar(20) [ 616P [ 633 ]]   628  Proj  ===  616  [[ 629  633 ]] #5 !jvms: BigDecimal::valueOf @ bci:20 (line 1293) BigDecimal::add @ bci:20 (line 4973) BigDecimal::add @ bci:18 (line 4980) BigDecimal::add @ bci:38 (line 1381) Foo::add1 @ bci:14 (line 36) Foo::funInt @ bci:14 (line 17)
LocalVar(24) [ 628 616P [ 713b 709b ]]   633  CheckCastPP  ===  630  628  [[ 645  645  726  713  713  709  709 ]]  #java/math/BigDecimal:NotNull:exact *  Oop:java/math/BigDecimal:NotNull:exact * !jvms: BigDecimal::valueOf @ bci:20 (line 1293) BigDecimal::add @ bci:20 (line 4973) BigDecimal::add @ bci:18 (line 4980) BigDecimal::add @ bci:38 (line 1381) Foo::add1 @ bci:14 (line 36) Foo::funInt @ bci:14 (line 17)

JavaObject(10) NoEscape(NoEscape) [ 257F 246F 254F 243F [ 161 166 ]]   149  Allocate  ===  136  88  138  8  1 ( 147  146  21  1  1  29  1  91  102  1  1  1  1  102  1  112 ) [[ 150  151  152  159  160  161 ]]  rawptr:NotNull ( int:>=0, java/lang/Object:NotNull *, bool, top, bool ) BigDecimal::valueOf @ bci:20 (line 1293) Foo::add1 @ bci:2 (line 33) Foo::funInt @ bci:14 (line 17) !jvms: BigDecimal::valueOf @ bci:20 (line 1293) Foo::add1 @ bci:2 (line 33) Foo::funInt @ bci:14 (line 17)
LocalVar(21) [ 149P [ 166 257b 246b ]]   161  Proj  ===  149  [[ 162  166  246  257 ]] #5 !jvms: BigDecimal::valueOf @ bci:20 (line 1293) Foo::add1 @ bci:2 (line 33) Foo::funInt @ bci:14 (line 17)
LocalVar(25) [ 161 149P [ 254b 243b ]]   166  CheckCastPP  ===  163  161  [[ 487  471  316  310  275  254  254  243  243 ]]  #java/math/BigDecimal:NotNull:exact *  Oop:java/math/BigDecimal:NotNull:exact * !jvms: BigDecimal::valueOf @ bci:20 (line 1293) Foo::add1 @ bci:2 (line 33) Foo::funInt @ bci:14 (line 17)

JavaObject(11) NoEscape(NoEscape) [ 416F 406F 413F 403F [ 328 333 ]]   316  Allocate  ===  306  160  277  8  1 ( 147  146  21  1  1  29  1  91  1  1  166  1  1  102  1  112 ) [[ 317  318  319  326  327  328 ]]  rawptr:NotNull ( int:>=0, java/lang/Object:NotNull *, bool, top, bool ) BigDecimal::valueOf @ bci:20 (line 1293) Foo::add1 @ bci:8 (line 34) Foo::funInt @ bci:14 (line 17) !jvms: BigDecimal::valueOf @ bci:20 (line 1293) Foo::add1 @ bci:8 (line 34) Foo::funInt @ bci:14 (line 17)
LocalVar(22) [ 316P [ 333 416b 406b ]]   328  Proj  ===  316  [[ 329  333  406  416 ]] #5 !jvms: BigDecimal::valueOf @ bci:20 (line 1293) Foo::add1 @ bci:8 (line 34) Foo::funInt @ bci:14 (line 17)
LocalVar(26) [ 328 316P [ 413b 403b ]]   333  CheckCastPP  ===  330  328  [[ 487  471  432  413  413  403  403 ]]  #java/math/BigDecimal:NotNull:exact *  Oop:java/math/BigDecimal:NotNull:exact * !jvms: BigDecimal::valueOf @ bci:20 (line 1293) Foo::add1 @ bci:8 (line 34) Foo::funInt @ bci:14 (line 17)

Scalar  616  Allocate  ===  606  327  350  8  1 ( 147  146  21  1  1  29  1  91  1  1  1  1  1  1  1  1  1  1  1  1  1  1  1  1  1  1  1  1  1  1  1  1  1  1  547  1  112 ) [[ 617  618  619  626  627  628 ]]  rawptr:NotNull ( int:>=0, java/lang/Object:NotNull *, bool, top, bool ) BigDecimal::valueOf @ bci:20 (line 1293) BigDecimal::add @ bci:20 (line 4973) BigDecimal::add @ bci:18 (line 4980) BigDecimal::add @ bci:38 (line 1381) Foo::add1 @ bci:14 (line 36) Foo::funInt @ bci:14 (line 17) !jvms: BigDecimal::valueOf @ bci:20 (line 1293) BigDecimal::add @ bci:20 (line 4973) BigDecimal::add @ bci:18 (line 4980) BigDecimal::add @ bci:38 (line 1381) Foo::add1 @ bci:14 (line 36) Foo::funInt @ bci:14 (line 17)
++++ Eliminated: 616 Allocate
Scalar  316  Allocate  ===  306  160  185  8  1 ( 147  146  21  1  1  29  1  91  1  1  166  1  1  102  1  112 ) [[ 317  318  319  326  327  328 ]]  rawptr:NotNull ( int:>=0, java/lang/Object:NotNull *, bool, top, bool ) BigDecimal::valueOf @ bci:20 (line 1293) Foo::add1 @ bci:8 (line 34) Foo::funInt @ bci:14 (line 17) !jvms: BigDecimal::valueOf @ bci:20 (line 1293) Foo::add1 @ bci:8 (line 34) Foo::funInt @ bci:14 (line 17)
++++ Eliminated: 316 Allocate
Scalar  166  CheckCastPP  ===  163  161  [[ 310 ]]  #java/math/BigDecimal:NotNull:exact *,iid=149  Oop:java/math/BigDecimal:NotNull:exact *,iid=149 !jvms: BigDecimal::valueOf @ bci:20 (line 1293) Foo::add1 @ bci:2 (line 33) Foo::funInt @ bci:14 (line 17)
++++ Eliminated: 149 Allocate
88

======== Connection graph for  Foo::add1
invocation #0: 2 iterations and 0.000005 sec to build connection graph with 777 nodes and worklist size 38

JavaObject(3) NoEscape(NoEscape) NSR [ 352F 348F 442F 464F [ 262 267 212 441 ]]   250  Allocate  ===  230  26  27  8  1 ( 68  67  33  1  1  1  1  29  1  1  10  1  22 ) [[ 251  252  253  260  261  262 ]]  rawptr:NotNull ( int:>=0, java/lang/Object:NotNull *, bool, top, bool ) BigDecimal::valueOf @ bci:20 (line 1293) Foo::add1 @ bci:8 (line 34) !jvms: BigDecimal::valueOf @ bci:20 (line 1293) Foo::add1 @ bci:8 (line 34)
LocalVar(18) [ 250P [ 267 ]]   262  Proj  ===  250  [[ 263  267 ]] #5 !jvms: BigDecimal::valueOf @ bci:20 (line 1293) Foo::add1 @ bci:8 (line 34)
LocalVar(24) [ 262 250P [ 352b 348b 212 ]]   267  CheckCastPP  ===  264  262  [[ 284  284  365  352  212  352  348  348 ]]  #java/math/BigDecimal:NotNull:exact *  Oop:java/math/BigDecimal:NotNull:exact * !jvms: BigDecimal::valueOf @ bci:20 (line 1293) Foo::add1 @ bci:8 (line 34)
LocalVar(25) [ 239 267 1P 250P [ 441 ]]   212  Phi  ===  208  239  267  [[ 441  387  424  429 ]]  #java/math/BigDecimal *  Oop:java/math/BigDecimal * !jvms: Foo::add1 @ bci:8 (line 34)
LocalVar(31) [ 212 1P 250P [ 442b 464b ]]   441  CastPP  ===  434  212  [[ 464  442  442  453  464 ]]  #java/math/BigDecimal:NotNull *  Oop:java/math/BigDecimal:NotNull * !jvms: BigDecimal::add @ bci:12 (line 1380) Foo::add1 @ bci:14 (line 36)

JavaObject(4) NoEscape(NoEscape) NSR [ 183F 177F 413F 460F [ 82 87 29 392 ]]   70  Allocate  ===  48  6  7  8  1 ( 68  67  33  1  1  10  1  1  1  1  10  1  22 ) [[ 71  72  73  80  81  82 ]]  rawptr:NotNull ( int:>=0, java/lang/Object:NotNull *, bool, top, bool ) BigDecimal::valueOf @ bci:20 (line 1293) Foo::add1 @ bci:2 (line 33) !jvms: BigDecimal::valueOf @ bci:20 (line 1293) Foo::add1 @ bci:2 (line 33)
LocalVar(21) [ 70P [ 87 ]]   82  Proj  ===  70  [[ 83  87 ]] #5 !jvms: BigDecimal::valueOf @ bci:20 (line 1293) Foo::add1 @ bci:2 (line 33)
LocalVar(27) [ 82 70P [ 183b 177b 29 ]]   87  CheckCastPP  ===  84  82  [[ 106  106  198  183  29  183  177  177 ]]  #java/math/BigDecimal:NotNull:exact *  Oop:java/math/BigDecimal:NotNull:exact * !jvms: BigDecimal::valueOf @ bci:20 (line 1293) Foo::add1 @ bci:2 (line 33)
LocalVar(26) [ 57 87 1P 70P [ 392 ]]   29  Phi  ===  25  57  87  [[ 284  392  234  250  379 ]]  #java/math/BigDecimal *  Oop:java/math/BigDecimal * !orig=[378] !jvms: Foo::add1 @ bci:2 (line 33)
LocalVar(33) [ 29 1P 70P [ 413b 460b ]]   392  CastPP  ===  384  29  [[ 460  453  424  413  413  460 ]]  #java/math/BigDecimal:NotNull *  Oop:java/math/BigDecimal:NotNull * !jvms: Foo::add1 @ bci:14 (line 36)

JavaObject(5) NoEscape(NoEscape) NSR [ 694F 690F 756F [ 604 609 551 735 ]]   592  Allocate  ===  572  209  210  8  1 ( 68  67  33  1  1  1  1  1  1  1  1  1  1  1  1  1  1  1  1  1  1  1  1  1  1  1  1  1  1  1  1  513  1  461 ) [[ 593  594  595  602  603  604 ]]  rawptr:NotNull ( int:>=0, java/lang/Object:NotNull *, bool, top, bool ) BigDecimal::valueOf @ bci:20 (line 1293) BigDecimal::add @ bci:20 (line 4973) BigDecimal::add @ bci:18 (line 4980) BigDecimal::add @ bci:38 (line 1381) Foo::add1 @ bci:14 (line 36) !jvms: BigDecimal::valueOf @ bci:20 (line 1293) BigDecimal::add @ bci:20 (line 4973) BigDecimal::add @ bci:18 (line 4980) BigDecimal::add @ bci:38 (line 1381) Foo::add1 @ bci:14 (line 36)
LocalVar(22) [ 592P [ 609 ]]   604  Proj  ===  592  [[ 605  609 ]] #5 !jvms: BigDecimal::valueOf @ bci:20 (line 1293) BigDecimal::add @ bci:20 (line 4973) BigDecimal::add @ bci:18 (line 4980) BigDecimal::add @ bci:38 (line 1381) Foo::add1 @ bci:14 (line 36)
LocalVar(28) [ 604 592P [ 694b 551 690b ]]   609  CheckCastPP  ===  606  604  [[ 626  626  707  694  551  694  690  690 ]]  #java/math/BigDecimal:NotNull:exact *  Oop:java/math/BigDecimal:NotNull:exact * !jvms: BigDecimal::valueOf @ bci:20 (line 1293) BigDecimal::add @ bci:20 (line 4973) BigDecimal::add @ bci:18 (line 4980) BigDecimal::add @ bci:38 (line 1381) Foo::add1 @ bci:14 (line 36)
LocalVar(29) [ 581 609 1P 592P [ 735 ]]   551  Phi  ===  547  581  609  [[ 735  723 ]]  #java/math/BigDecimal *  Oop:java/math/BigDecimal * !orig=[722] !jvms: BigDecimal::add @ bci:20 (line 4973) BigDecimal::add @ bci:18 (line 4980) BigDecimal::add @ bci:38 (line 1381) Foo::add1 @ bci:14 (line 36)
LocalVar(35) [ 551 1P 592P [ 756b ]]   735  CastPP  ===  728  551  [[ 756  756 ]]  #java/math/BigDecimal:NotNull *  Oop:java/math/BigDecimal:NotNull * !jvms: Foo::add1 @ bci:21 (line 38)


======== Connection graph for  Foo::funLong
invocation #0: 2 iterations and 0.000007 sec to build connection graph with 883 nodes and worklist size 42

JavaObject(5) NoEscape(NoEscape) NSR [ 782F 778F 844F [ 692 697 639 823 ]]   680  Allocate  ===  660  297  298  8  1 ( 159  158  21  1  1  29  1  94  1  1  1  1  1  1  1  1  1  1  1  1  1  1  1  1  1  1  1  1  1  1  1  1  1  1  1  601  1  549 ) [[ 681  682  683  690  691  692 ]]  rawptr:NotNull ( int:>=0, java/lang/Object:NotNull *, bool, top, bool ) BigDecimal::valueOf @ bci:20 (line 1293) BigDecimal::add @ bci:20 (line 4973) BigDecimal::add @ bci:18 (line 4980) BigDecimal::add @ bci:38 (line 1381) Foo::add1 @ bci:14 (line 36) Foo::funLong @ bci:15 (line 26) !jvms: BigDecimal::valueOf @ bci:20 (line 1293) BigDecimal::add @ bci:20 (line 4973) BigDecimal::add @ bci:18 (line 4980) BigDecimal::add @ bci:38 (line 1381) Foo::add1 @ bci:14 (line 36) Foo::funLong @ bci:15 (line 26)
LocalVar(22) [ 680P [ 697 ]]   692  Proj  ===  680  [[ 693  697 ]] #5 !jvms: BigDecimal::valueOf @ bci:20 (line 1293) BigDecimal::add @ bci:20 (line 4973) BigDecimal::add @ bci:18 (line 4980) BigDecimal::add @ bci:38 (line 1381) Foo::add1 @ bci:14 (line 36) Foo::funLong @ bci:15 (line 26)
LocalVar(28) [ 692 680P [ 782b 778b 639 ]]   697  CheckCastPP  ===  694  692  [[ 714  714  795  782  639  782  778  778 ]]  #java/math/BigDecimal:NotNull:exact *  Oop:java/math/BigDecimal:NotNull:exact * !jvms: BigDecimal::valueOf @ bci:20 (line 1293) BigDecimal::add @ bci:20 (line 4973) BigDecimal::add @ bci:18 (line 4980) BigDecimal::add @ bci:38 (line 1381) Foo::add1 @ bci:14 (line 36) Foo::funLong @ bci:15 (line 26)
LocalVar(33) [ 669 697 1P 680P [ 823 ]]   639  Phi  ===  635  669  697  [[ 823  811 ]]  #java/math/BigDecimal *  Oop:java/math/BigDecimal * !orig=[810] !jvms: BigDecimal::add @ bci:20 (line 4973) BigDecimal::add @ bci:18 (line 4980) BigDecimal::add @ bci:38 (line 1381) Foo::add1 @ bci:14 (line 36) Foo::funLong @ bci:15 (line 26)
LocalVar(39) [ 639 1P 680P [ 844b ]]   823  CastPP  ===  816  639  [[ 844  844 ]]  #java/math/BigDecimal:NotNull *  Oop:java/math/BigDecimal:NotNull * !jvms: Foo::add1 @ bci:21 (line 38) Foo::funLong @ bci:15 (line 26)

JavaObject(6) NoEscape(NoEscape) NSR [ 440F 436F 530F 552F [ 350 355 300 529 ]]   338  Allocate  ===  318  120  121  8  1 ( 159  158  21  1  1  29  1  94  1  1  1  123  1  1  94  1  116 ) [[ 339  340  341  348  349  350 ]]  rawptr:NotNull ( int:>=0, java/lang/Object:NotNull *, bool, top, bool ) BigDecimal::valueOf @ bci:20 (line 1293) Foo::add1 @ bci:8 (line 34) Foo::funLong @ bci:15 (line 26) !jvms: BigDecimal::valueOf @ bci:20 (line 1293) Foo::add1 @ bci:8 (line 34) Foo::funLong @ bci:15 (line 26)
LocalVar(23) [ 338P [ 355 ]]   350  Proj  ===  338  [[ 351  355 ]] #5 !jvms: BigDecimal::valueOf @ bci:20 (line 1293) Foo::add1 @ bci:8 (line 34) Foo::funLong @ bci:15 (line 26)
LocalVar(29) [ 350 338P [ 440b 436b 300 ]]   355  CheckCastPP  ===  352  350  [[ 372  372  453  440  300  440  436  436 ]]  #java/math/BigDecimal:NotNull:exact *  Oop:java/math/BigDecimal:NotNull:exact * !jvms: BigDecimal::valueOf @ bci:20 (line 1293) Foo::add1 @ bci:8 (line 34) Foo::funLong @ bci:15 (line 26)
LocalVar(31) [ 327 355 1P 338P [ 529 ]]   300  Phi  ===  296  327  355  [[ 529  475  512  517 ]]  #java/math/BigDecimal *  Oop:java/math/BigDecimal * !jvms: Foo::add1 @ bci:8 (line 34) Foo::funLong @ bci:15 (line 26)
LocalVar(37) [ 300 1P 338P [ 530b 552b ]]   529  CastPP  ===  522  300  [[ 552  530  530  541  552 ]]  #java/math/BigDecimal:NotNull *  Oop:java/math/BigDecimal:NotNull * !jvms: BigDecimal::add @ bci:12 (line 1380) Foo::add1 @ bci:14 (line 36) Foo::funLong @ bci:15 (line 26)

JavaObject(7) NoEscape(NoEscape) NSR [ 271F 267F 501F 548F [ 173 178 123 480 ]]   161  Allocate  ===  139  91  141  8  1 ( 159  158  21  1  1  29  1  94  1  94  1  1  1  1  94  1  116 ) [[ 162  163  164  171  172  173 ]]  rawptr:NotNull ( int:>=0, java/lang/Object:NotNull *, bool, top, bool ) BigDecimal::valueOf @ bci:20 (line 1293) Foo::add1 @ bci:2 (line 33) Foo::funLong @ bci:15 (line 26) !jvms: BigDecimal::valueOf @ bci:20 (line 1293) Foo::add1 @ bci:2 (line 33) Foo::funLong @ bci:15 (line 26)
LocalVar(24) [ 161P [ 178 ]]   173  Proj  ===  161  [[ 174  178 ]] #5 !jvms: BigDecimal::valueOf @ bci:20 (line 1293) Foo::add1 @ bci:2 (line 33) Foo::funLong @ bci:15 (line 26)
LocalVar(30) [ 173 161P [ 271b 267b 123 ]]   178  CheckCastPP  ===  175  173  [[ 197  197  286  271  123  271  267  267 ]]  #java/math/BigDecimal:NotNull:exact *  Oop:java/math/BigDecimal:NotNull:exact * !jvms: BigDecimal::valueOf @ bci:20 (line 1293) Foo::add1 @ bci:2 (line 33) Foo::funLong @ bci:15 (line 26)
LocalVar(32) [ 148 178 1P 161P [ 480 ]]   123  Phi  ===  119  148  178  [[ 372  480  322  338  467 ]]  #java/math/BigDecimal *  Oop:java/math/BigDecimal * !orig=[466] !jvms: Foo::add1 @ bci:2 (line 33) Foo::funLong @ bci:15 (line 26)
LocalVar(38) [ 123 1P 161P [ 501b 548b ]]   480  CastPP  ===  472  123  [[ 548  541  512  501  501  548 ]]  #java/math/BigDecimal:NotNull *  Oop:java/math/BigDecimal:NotNull * !jvms: Foo::add1 @ bci:14 (line 36) Foo::funLong @ bci:15 (line 26)

2987

from tencentkona-8.

tansm avatar tansm commented on July 28, 2024

非常感谢您的回馈,我上午也做了一些其他尝试,也分享给您。

新的funLong2() 方法使用 while 循环,即使使用 long 作为变量,也不会造成第二个方法变慢,这个很重要,

import java.math.BigDecimal;

public class Foo {
    public static void main(String[] args) {
        System.out.println(funInt());
        System.out.println(funLong2());
    }

    static long funInt() {
        long start = System.currentTimeMillis();
        for(int i = 0; i < Integer.MAX_VALUE; i++) {
            add1((long) i);
        }

        return System.currentTimeMillis() - start;
    }

    static long funLong() {
        long start = System.currentTimeMillis();
        for(long i = 0L; i < (long) Integer.MAX_VALUE; i++) {
            add1(i);
        }

        return System.currentTimeMillis() - start;
    }
    
    static long funLong2() {
        long start = System.currentTimeMillis();
        long i = 0L;
        long len = (long) Integer.MAX_VALUE;
        while(i++ < len){
            add1(i);
        }

        return System.currentTimeMillis() - start;
    }

    static void add1(long i) {
        BigDecimal a = BigDecimal.valueOf(i, 2);
        BigDecimal b = BigDecimal.valueOf(i, 2);

        BigDecimal c = a.add(b);

        if(c.scale() != 2){
            throwError();
        }
    }
    
    static void add2(long i) {
        long a = i;
        long b = i + 1L;
        long c = a + b;

        if(c < 0L){
            throwError();
        }
    }

    static void throwError() {
        throw new RuntimeException("error");
    }
}

第二点,我最初怀疑是分配了更多的对象导致 GC,但我修改了 add1(),如果 c 变量也是直接创建一个BigDecimal,而不是使用 加法 运算,也不会出现问题。

from tencentkona-8.

tansm avatar tansm commented on July 28, 2024

我发现 https://heapdump.cn/question/3686888 也提到这个问题。

from tencentkona-8.

casparcwang avatar casparcwang commented on July 28, 2024

openjdk主干库截止目前JDK19(afa5d4ced38b7f3752932c28af96d8fc600d1df7)的Escape Analysis的实现依然比较脆弱,很容易导致EA分析失败,从而无法进行Stack Allocation for Aggregates,具体参见文章https://cr.openjdk.java.net/~cslucas/escape-analysis/EscapeAnalysis.html

from tencentkona-8.

casparcwang avatar casparcwang commented on July 28, 2024

非常感谢您的回馈,我上午也做了一些其他尝试,也分享给您。

新的funLong2() 方法使用 while 循环,即使使用 long 作为变量,也不会造成第二个方法变慢,这个很重要,

import java.math.BigDecimal;

public class Foo {
    public static void main(String[] args) {
        System.out.println(funInt());
        System.out.println(funLong2());
    }

    static long funInt() {
        long start = System.currentTimeMillis();
        for(int i = 0; i < Integer.MAX_VALUE; i++) {
            add1((long) i);
        }

        return System.currentTimeMillis() - start;
    }

    static long funLong() {
        long start = System.currentTimeMillis();
        for(long i = 0L; i < (long) Integer.MAX_VALUE; i++) {
            add1(i);
        }

        return System.currentTimeMillis() - start;
    }
    
    static long funLong2() {
        long start = System.currentTimeMillis();
        long i = 0L;
        long len = (long) Integer.MAX_VALUE;
        while(i++ < len){
            add1(i);
        }

        return System.currentTimeMillis() - start;
    }

    static void add1(long i) {
        BigDecimal a = BigDecimal.valueOf(i, 2);
        BigDecimal b = BigDecimal.valueOf(i, 2);

        BigDecimal c = a.add(b);

        if(c.scale() != 2){
            throwError();
        }
    }
    
    static void add2(long i) {
        long a = i;
        long b = i + 1L;
        long c = a + b;

        if(c < 0L){
            throwError();
        }
    }

    static void throwError() {
        throw new RuntimeException("error");
    }
}

第二点,我最初怀疑是分配了更多的对象导致 GC,但我修改了 add1(),如果 c 变量也是直接创建一个BigDecimal,而不是使用 加法 运算,也不会出现问题。

您说的这个测试主要是由于i=0传入static void add1(long i) ,导致add1最终inline了java.math.BigDecimal::zeroValueOf,使得该函数导致控制流改变,进而EA失效。而您的funLong2是从1开始调用add1java.math.BigDecimal::zeroValueOf调用不到,EA此时是有效的。

    335   31 %     3       Foo::funInt @ 6 (29 bytes)   made not entrant
                              @ 14   Foo::add1 (32 bytes)   inline (hot)
                                @ 2   java.math.BigDecimal::valueOf (46 bytes)   inline (hot)
                                  @ 42   java.math.BigDecimal::<init> (27 bytes)   inline (hot)
                                    @ 1   java.lang.Number::<init> (5 bytes)   inline (hot)
                                      @ 1   java.lang.Object::<init> (1 bytes)   inline (hot)
                                @ 8   java.math.BigDecimal::valueOf (46 bytes)   inline (hot)
                                  @ 42   java.math.BigDecimal::<init> (27 bytes)   inline (hot)
                                    @ 1   java.lang.Number::<init> (5 bytes)   inline (hot)
                                      @ 1   java.lang.Object::<init> (1 bytes)   inline (hot)
                                @ 14   java.math.BigDecimal::add (113 bytes)   inline (hot)
                                  @ 38   java.math.BigDecimal::add (189 bytes)   inline (hot)
                                    @ 18   java.math.BigDecimal::add (42 bytes)   inline (hot)
                                      @ 2   java.math.BigDecimal::add (26 bytes)   inline (hot)
                                      @ 20   java.math.BigDecimal::valueOf (46 bytes)   inline (hot)
                                        @ 42   java.math.BigDecimal::<init> (27 bytes)   inline (hot)
                                          @ 1   java.lang.Number::<init> (5 bytes)   inline (hot)
                                            @ 1   java.lang.Object::<init> (1 bytes)   inline (hot)
                                @ 21   java.math.BigDecimal::scale (5 bytes)   accessor

   1043   44 %     4       Foo::funLong @ 6 (31 bytes)
   1089   42 %     3       Foo::funLong @ 6 (31 bytes)   made not entrant
                              @ 15   Foo::add1 (32 bytes)   inline (hot)
                                @ 2   java.math.BigDecimal::valueOf (46 bytes)   inline (hot)
                                  @ 16   java.math.BigDecimal::zeroValueOf (32 bytes)   low call site frequency
                                  @ 42   java.math.BigDecimal::<init> (27 bytes)   inline (hot)
                                    @ 1   java.lang.Number::<init> (5 bytes)   inline (hot)
                                      @ 1   java.lang.Object::<init> (1 bytes)   inline (hot)
                                @ 8   java.math.BigDecimal::valueOf (46 bytes)   inline (hot)
                                  @ 16   java.math.BigDecimal::zeroValueOf (32 bytes)   low call site frequency
                                  @ 42   java.math.BigDecimal::<init> (27 bytes)   inline (hot)
                                    @ 1   java.lang.Number::<init> (5 bytes)   inline (hot)
                                      @ 1   java.lang.Object::<init> (1 bytes)   inline (hot)
                                @ 14   java.math.BigDecimal::add (113 bytes)   inline (hot)
                                  @ 38   java.math.BigDecimal::add (189 bytes)   inline (hot)
                                    @ 18   java.math.BigDecimal::add (42 bytes)   inline (hot)
                                      @ 2   java.math.BigDecimal::add (26 bytes)   inline (hot)
                                      @ 20   java.math.BigDecimal::valueOf (46 bytes)   inline (hot)
                                        @ 16   java.math.BigDecimal::zeroValueOf (32 bytes)   low call site frequency
                                        @ 42   java.math.BigDecimal::<init> (27 bytes)   inline (hot)
                                          @ 1   java.lang.Number::<init> (5 bytes)   inline (hot)
                                            @ 1   java.lang.Object::<init> (1 bytes)   inline (hot)
                                @ 21   java.math.BigDecimal::scale (5 bytes)   accessor

from tencentkona-8.

tansm avatar tansm commented on July 28, 2024

@casparcwang 我想再请教一下,为什么JAVA中,for 循环使用int 作为变量 比 long 作为变量,其性能要快 2~3 倍,while循环也是如此,感谢。

from tencentkona-8.

casparcwang avatar casparcwang commented on July 28, 2024

@casparcwang 我想再请教一下,为什么JAVA中,for 循环使用int 作为变量 比 long 作为变量,其性能要快 2~3 倍,while循环也是如此,感谢。

在java里面,for或者while循环除了int/long作为循环变量,其他均相同的情况下,应该是没有本质的区别的,特别是在解释器模式(-Xint)下或者C1编译器模式(-XX:TieredStopAtLevel=3)下。C2的话可能会根据inline的情况而有所不同,特别是在OSR的情况下,您最初的例子中如果把add1改成add2,并且funcInt和funcLong多执行几次,就会发现最终两者的执行时间是一样的,都为0.

当然在你说的例子中,前一两次执行的时候使用的是OSR的JIT代码,int和long作为循环变量时的jit代码效率不同,是一个值得分析和改进的点。

from tencentkona-8.

tansm avatar tansm commented on July 28, 2024

非常感谢您的回答,学习到了很多的知识。

from tencentkona-8.

tansm avatar tansm commented on July 28, 2024

https://www.cnblogs.com/thisiswhy/p/16657667.html
这篇文章解释了long 和 int 作为循环变量时的区别,即 long 作为变量时会插入安全点。

from tencentkona-8.

casparcwang avatar casparcwang commented on July 28, 2024

https://www.cnblogs.com/thisiswhy/p/16657667.html
这篇文章解释了long 和 int 作为循环变量时的区别,即 long 作为变量时会插入安全点。

我个人是不建议采用Thread.sleep这种写法的,int作为循环变量确实现在没有插入safepoint instruction,而long作为循环变量会插入,但是一般遇到这种情况是推荐加上选项-XX:+UseCountedLoopSafepoints来强制编译插入safepoint instruction。

from tencentkona-8.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.