《深入理解计算机系统》——(一)

一、条件数据传送和条件控制转移

首先我们先从代码层面看下这两者的不同点,先给出结论:条件数据传送性能>条件控制转移性能

public class IfTest {
    private static int absDiff(int x, int y) {
        int result;
        if (x < y) {
            result = y - x;
        } else {
            result = x - y;
        }
        return result;
    }


    private static int cmovDiff(int x, int y) {
        int rval = y - x;
        int eval = x - y;
        boolean nTest = x >= y;
        if (nTest) {
            rval = eval;
        }
        return rval;
    }

    public static void main(String[] args) {
        int x = 998, y = 999;
        System.out.println("absDiff start");
        long startTime = System.currentTimeMillis();
        System.out.println(absDiff(x, y));
        long endTime = System.currentTimeMillis();
        System.out.println("absDiff start time=" + (endTime - startTime));

        System.out.println("cmovDiff start");
        startTime = System.currentTimeMillis();
        System.out.println(cmovDiff(x, y));
        endTime = System.currentTimeMillis();
        System.out.println("cmovDiff start time=" + (endTime - startTime));
    }
}

自己可以试验下两者的所用时间比较,下面来具体分析下原因:

处理器通过使用流水线获得高性能,在流水线中,一条指令的处理要经过一系列的阶段,每个阶段执行所需操作的一小部分(例如,从内存中取指令,确定指令类型,从 内存读数据,执行算数运算,向内存写数据,以及更新程序计数器等)。这种方法是通过重叠连续指令的步骤来提高性能,例如,在取一条指令的同时,执行他前面的一条指令的算数运算。但是要做到这一点,就需要事先确定要执行的指令序列,这样才能保证流水线中充满了待执行的指令。当机器遇到条件分支的时候,只有当条件求值完成之后才能确定走哪个分支。但是现在机器不会那么傻的自己去等待而不做别的事,他会采用非常精密的分支预测逻辑猜测每条跳转逻辑是否会执行,然后将概率最大的那个分支的指令放在流水线中,如果在成功率比较高的情况下,其实效率还是比较高的,但是如果是上图中的x

二、switch语句

正常我们在开发的过程中,如果遇到条件分支都是建议使用switch语句,话说是效率会高点,那为什么呢?其实也不是什么情况都适用,只有在需要处理具有多种可能结果的预测时,这种语句才会特别有用,接下来一探究竟:

首先switch的底层数据结构是跳转表。跳转表是一个数组,表项i是一个代码段的地址,这个代码段实现当开关索引值等于i时程序应该采取的动作。程序代码用开关索引值来执行一个跳转表内的数组引用,确定跳转表的目标,和使用一组很长的if-else相比,使用跳转表的优点就是执行开关语句的时间与开关情况的数量无关。GCC根据开关情况的数量和开关情况值的稀疏程度来翻译开关语句,当开关情况数量比较多时(4个以上),并且值的跨度比较小时,就会使用跳转表。

 

你可能感兴趣的:(深入理解计算机系统)