有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!


共 (5) 个答案

  1. # 1 楼答案

    有几件事会起作用,对实际性能的最终影响是您需要根据您的用例来衡量的。我认为这是一种你经常发现的方法:

    1. 分支预测-如果var几乎总是错误的,这就是代码所建议的,那么分支预测几乎总是正确的。如果字段经常更改,则这将成为一个经常预测失误的分支,并且成本高昂

    2. 读取未命中-如果var大部分是读取的(并且读取了很多),那么避免无故更改可以帮助您的软件不会使它所在的缓存线无效。如果您对它进行写入,那么读取它(以及同一缓存线上的任何内容)的每个其他内核都需要获得一个新的副本,该副本将经历读未命中。这意味着,为了使读取具有更一致的速度,上述方法可能值得降低速度

    3. 写入成本与读取成本-如果var是易变的,那么它的写入是一个负载存储障碍,这相当昂贵。相比之下,读取volatile(负载屏障)是相当便宜的(对于经常使用且几乎没有更改的值的缓存命中)。相比之下,这可以使分支非常便宜

    这是一个优化的人,例子可以在JDK(Irc)中找到,我想你有理由考虑它。

  2. # 2 楼答案

    第一个代码包含一个比较,因此编译器可能会生成如下所示的java字节码:

      public static void main(java.lang.String[]);
        Code:
           0: iconst_1      
           1: istore_1      
           2: iload_1       
           3: ifeq          8
           6: iconst_0      
           7: istore_1      
           8: return    
    

    对于第二个代码生成的字节码较短,因为缺少比较:

      public static void main(java.lang.String[]);
        Code:
           0: iconst_1      
           1: istore_1      
           2: iconst_0      
           3: istore_1      
           4: return      
    

    在第一个示例中,虚拟机执行8个命令所需的时间比在第二个示例中执行4个命令所需的时间多。虽然这个差别不应该太大,但第二个代码更清楚

    将代码放在一个简单的main方法中并编译该类。然后运行命令提示符并更改为java/bin目录。要反汇编类调用javap -c path/to/YourClass.class >> path/to/bytecode.txt。字节码。txt将包含类的java字节码

  3. # 3 楼答案

    “速度差异”(如果有的话)将完全取决于JVM。任何优秀的编译器都应该能够优化测试,在这一点上,两者是相同的

    例外:如果var被声明为volatile,则条件版本将始终较慢

    在任何情况下,如果性能至关重要,最好的选择是在预期条件下(机器、系统、JVM、典型负载等)测量性能

  4. # 4 楼答案

    这是另一个廉价的“基准”(几乎不配使用这个术语)。对我来说,对于OP的问题,猴子扳手的基准测试的结果并不是很清楚,所以我想我也应该把它放在这里

    结果(在这些条件下,并且仅在很少的测试中):在编写局部布尔值之前检查它比在没有必要的情况下经常编写要好

    public static void main(String[] args) {
    
        final Random r = new Random(0);
    
        boolean b = false;
        boolean decision;
    
        long startTime;
        long endTime;
    
        startTime = System.currentTimeMillis();
        for (long i = 0; i < 1000000000; i++) {
            decision = r.nextDouble() > 0.1; // Will be true MOST of the time.
    
            if (decision) {
    
                // if (!b) {
                    b = true;
                // }
    
            }
        }
        endTime = System.currentTimeMillis();
    
        System.err.println(endTime - startTime);
        System.err.println(b);
    
        System.exit(0);
    }
    
    With bluntly writing (ms):
    18139
    18140
    18196
    (18220)
    (18181)
    ----------
    Average of 3: 18158.333333333333333333333333333
    Average of 5: 18175.2
    
    
    With checking before writing (ms):
    18097
    18109
    18115
    (18129)
    (18133)
    ----------
    Average of 3: 18107
    Average of 5: 18116.6
    
    
    With checking, it only takes this % (3 samples): 99.71730151445617255621844882974
    With checking, it only takes this % (5 samples): 99.677582640080989480170782164708
    

    通过检查,大约需要99.7%的书写时间。如果写操作不必要地发生,通常。在这个糟糕的“基准”中,也就是说

  5. # 5 楼答案

    我在这场比赛中迟到了,但我写这个测试课是为了回答一个类似的问题

    package SpeedTests;
    
    import java.text.NumberFormat;
    import java.util.Locale;
    
    public class BooleanSpeedTest {
    
        public static void main(String[] args) {
            boolean BoolTest = true;
            long LongLoop = 100000;
            long TrueLoopCount = 0;
            long FalseLoopCount = 0;
            long TimeTotal = 0;
    
            long startTime;
            long endTime;
    
            for(int intLoopA = 1; intLoopA < 6; intLoopA++) {
                LongLoop = LongLoop * 10;
                TimeTotal = 0;
                System.out.println("");
                System.out.print(
                        NumberFormat.getNumberInstance(Locale.US).format(LongLoop) + " - ");
    
                for(int intLoopM = 0; intLoopM < 20; intLoopM++) {
                    TrueLoopCount = 0;
                    FalseLoopCount = 0;
                    startTime = System.currentTimeMillis();
    
                    for(long LoopCount = 0; LoopCount < LongLoop; LoopCount++) {
                        if(!BoolTest) {
                            TrueLoopCount++;
                        }
                        else
                            FalseLoopCount++;   
                    }
                    endTime = System.currentTimeMillis();
                    System.out.print( (endTime - startTime) + "ms ");
                    TimeTotal += ((endTime - startTime) );    
                }
    
                System.out.print(" AVG: " + (TimeTotal/20));
            }
        }
    }
    

    我的结果: 每个循环的平均时间/十亿(毫秒)注释时间

    if(BoolTest)                    443                     When False      0.00000443
    if(BoolTest)                    443                     When True
    
    if(BoolTest == false)           443                     When False
    if(BoolTest == false)           442                     When True
    
    if(!BoolTest)                   438                     When False      
    if(!BoolTest)                   441                     When True
    
    (BoolTest ? Var++ : Var--)      435                     When True
    (BoolTest ? Var++ : Var--)      435                     When False