[netty] 体会netty对性能的苛刻,EventExecu

2018-08-23  本文已影响0人  良辰夜

一. 证明性能上:& >> %

在常识中,我们普遍认为 位运算操作符"&" 的性能比取余运算符"%"高,因为"&"是自己面向cpu的指令,而"%"可能需要转换。

        int len = 10_0000_0000;
        long l ;

        l = System.currentTimeMillis();
        for(int i=1;i<len;i++){
            int c = i & i;
        }
        System.out.println("&: " + System.currentTimeMillis() - l);

        l = System.currentTimeMillis();
        for(int i=1;i<len;i++){
            int c = i % i;
        }
        System.out.println("%: " + System.currentTimeMillis() - l);

我们多次打印后得到结果:

&: 458
%: 3438

我们大概能得到一个结论:
位运算操作符"&"的性能大概是运算符"%"的8倍到9倍间

二. netty EventExecutorChooserFactory

这是一个EventExecutor的选择器的factory,而netty的作者居然考虑到选择的时候 是用"%"还是 "&" 来实现 next功能

  1. 生成EventExecutorChooser
public EventExecutorChooser newChooser(EventExecutor[] executors) {
        if (isPowerOfTwo(executors.length)) {
            return new PowerOfTwoEventExecutorChooser(executors);
        } else {
            return new GenericEventExecutorChooser(executors);
        }
    }
  1. 通过是否为 2的次方。
    2的次方首先要满足一个条件,在int表示的4个字节的32个位中,除了首位,有且仅有一个bit上为1,其他为0。例如:00001000
    private static boolean isPowerOfTwo(int val) {
        return (val & -val) == val;//看清楚,是"-",不是"~"
    }

我们可以这么理解:
我们观察这种数字特征:00001000
00001000 & 11111000刚好可以得到原始值 00001000

  1. 为甚我需要一个2的次方?

因为2的次方 -1 后,刚好后面的数全是1。
0001000 - 1 = 00000111
而这个数我们可以&来做循环。

基数
: 00000011
1: 00000001
2: 00000010
3: 00000011
1: 00000101
2: 00000110
...

  1. 最后看看源码

可以看出 如果是这种数 00001111,尾巴连续1的数,就采用"&"去做循环next,如果不是就直接用"%"

    private static final class PowerOfTwoEventExecutorChooser implements EventExecutorChooser {
        private final AtomicInteger idx = new AtomicInteger();
        private final EventExecutor[] executors;

        @Override
        public EventExecutor next() {
            return executors[idx.getAndIncrement() & executors.length - 1];
        }
    }

    private static final class GenericEventExecutorChooser implements EventExecutorChooser {
        private final AtomicInteger idx = new AtomicInteger();
        private final EventExecutor[] executors;

        @Override
        public EventExecutor next() {
            return executors[Math.abs(idx.getAndIncrement() % executors.length)];
        }
    }
上一篇 下一篇

猜你喜欢

热点阅读