Google面试题解说性能之三:不要小看循环中的任何一个语句

对于任何语言来讲,循环永远是非分布式系统的性能的最大杀手,循环中的任何一个简单的语句对性能都是有影响的,只是影响的大小不同而已。第一个例子中的影响是比较大的,不同的实现方法的时间开销不同,然后这个微小的差异被循环次数放大后就非常的明显(3倍),而第二个例子,其本质是减少了循环执行的次数,虽然总的循环次数是一样的,但是最耗时的操作的执行次数被减少到1/10,所以产生的差异是非常巨大的(8倍)。我们再来看一个很不起眼的微小差异带来的影响:
public class GoogleFn {
    private static int MAX = 132000000;

    private static int MAX2 = MAX / 10;

    private static int count(int n) {
        int count = 0;
        while (n > 0) {
            int mod = n % 10;
            if (mod == 1)
                count++;
            n = n / 10;
        }
        return count;
    }

    private static void method1() {
        long start = System.currentTimeMillis();
        int result = 0;
        for (int i = 0; i < MAX2; i++) {
            int number = i * 10;
            int value = count(number);
            for (int j = 0; j < 10; j++) {
                result += value;
                if (j == 1) {
                    result++;
                }
                int x = number + j;
                if (x != 0 && result == x) {
                    print(x, start);
                }
            }
        }
    }

    private static void method2() {
        long start = System.currentTimeMillis();
        int result = 0;
        for (int i = 0; i < MAX2; i++) {
            int number = i * 10;
            int value = count(number);
            for (int j = 0; j < 10; j++) {
                result += value;
                if (j == 1) {
                    result++;
                }
                int x = number + j;
                if (result == x && x != 0) {
                    print(x, start);
                }
            }
        }
    }

    private static void print(int i, long start) {
        System.out.println("Find " + i + ", " + (System.currentTimeMillis() - start) + "ms");
    }

    public static void main(String[] args) {
        method1();
        method2();
    }
}
运行结果:
Find 1, 0ms
Find 199981, 16ms
Find 199982, 16ms
Find 199983, 16ms
Find 199984, 16ms
Find 199985, 16ms
Find 199986, 16ms
Find 199987, 16ms
Find 199988, 16ms
Find 199989, 16ms
Find 199990, 16ms
Find 200000, 16ms
Find 200001, 16ms
Find 1599981, 63ms
Find 1599982, 63ms
Find 1599983, 63ms
Find 1599984, 63ms
Find 1599985, 63ms
Find 1599986, 63ms
Find 1599987, 78ms
Find 1599988, 78ms
Find 1599989, 78ms
Find 1599990, 78ms
Find 2600000, 110ms
Find 2600001, 110ms
Find 13199998, 531ms
Find 35000000, 1453ms
Find 35000001, 1453ms
Find 35199981, 1453ms
Find 35199982, 1453ms
Find 35199983, 1453ms
Find 35199984, 1453ms
Find 35199985, 1453ms
Find 35199986, 1453ms
Find 35199987, 1453ms
Find 35199988, 1453ms
Find 35199989, 1453ms
Find 35199990, 1453ms
Find 35200000, 1453ms
Find 35200001, 1453ms
Find 117463825, 5000ms
Find 1, 0ms
Find 199981, 16ms
Find 199982, 16ms
Find 199983, 16ms
Find 199984, 16ms
Find 199985, 16ms
Find 199986, 16ms
Find 199987, 16ms
Find 199988, 16ms
Find 199989, 16ms
Find 199990, 16ms
Find 200000, 16ms
Find 200001, 16ms
Find 1599981, 63ms
Find 1599982, 63ms
Find 1599983, 63ms
Find 1599984, 63ms
Find 1599985, 63ms
Find 1599986, 63ms
Find 1599987, 78ms
Find 1599988, 78ms
Find 1599989, 78ms
Find 1599990, 78ms
Find 2600000, 109ms
Find 2600001, 109ms
Find 13199998, 516ms
Find 35000000, 1438ms
Find 35000001, 1438ms
Find 35199981, 1438ms
Find 35199982, 1438ms
Find 35199983, 1438ms
Find 35199984, 1438ms
Find 35199985, 1438ms
Find 35199986, 1438ms
Find 35199987, 1438ms
Find 35199988, 1438ms
Find 35199989, 1438ms
Find 35199990, 1438ms
Find 35200000, 1438ms
Find 35200001, 1438ms
Find 117463825, 4938ms

注意我们的MAX值比以前的例子放大了10倍,因为这个例子的差异比较小,值太小看不出差异,注意到两个方法的不同了吗?对,仅仅是if里面的条件换了个位置:
x != 0 && result == x  -》 result == x && x != 0
你还可以稍稍修改下代码,把后面的那个的&& x != 0去掉,你会发现它的结果和这个结果很类似。
这个原理就是&&运算符的短路原理,如果前面的条件不为true,那么后面的计算不被执行。
所以循环中的任何代码都要比较小心,即使一点细小的不同都会在循环的放大作用下产生一些不好的结果。

PS: 条件判断中有多个并列条件时,前面放的应该是最少满足的条件,这样可以更好的过滤。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值