前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Netty对底层Selector的优化

Netty对底层Selector的优化

作者头像
书唐瑞
发布2022-06-02 13:46:10
2420
发布2022-06-02 13:46:10
举报
文章被收录于专栏:Netty历险记

在创建NioEventLoop时会封装一个JDK底层的Selector属性

代码语言:javascript
复制
private Selector selector;

那么我们简单看一下这个Selector在JDK层面的实现

代码语言:javascript
复制
public abstract class SelectorImpl extends AbstractSelector {
    protected Set<SelectionKey> selectedKeys = new HashSet();
    protected HashSet<SelectionKey> keys = new HashSet();
    private Set<SelectionKey> publicKeys;
    private Set<SelectionKey> publicSelectedKeys;


    protected SelectorImpl(SelectorProvider var1) {
        super(var1);
        if (Util.atBugLevel("1.4")) {
            this.publicKeys = this.keys;
            this.publicSelectedKeys = this.selectedKeys;
        } else {
            this.publicKeys = Collections.unmodifiableSet(this.keys);
            this.publicSelectedKeys = Util.ungrowableSet(this.selectedKeys);
        }
    }
}

从源码中我们可以发现, 当服务器监听到事件后会封装成SelectionKey放到HashSet中, 然后程序就可以从这个HashSet中取出事件进行处理.

而HashSet的add方法的时间复杂度是O(n), 为此Netty通过反射机制, 将底层的这个HashSet用数组替换了, 毕竟向数组中添加数据的时间复杂度是O(1), 那么我们从代码中找到答案吧.

代码语言:javascript
复制
NioEventLoop(NioEventLoopGroup parent, Executor executor, SelectorProvider selectorProvider,
                 SelectStrategy strategy, RejectedExecutionHandler rejectedExecutionHandler) {
        
    selector = openSelector();
}

跟进openSelector()方法

代码语言:javascript
复制
private SelectorTuple openSelector() {
  final SelectedSelectionKeySet selectedKeySet = new SelectedSelectionKeySet();
}

它创建了一个SelectedSelectionKeySet对象, 我们再看下这个类

代码语言:javascript
复制
final class SelectedSelectionKeySet extends AbstractSet<SelectionKey> {


    SelectionKey[] keys;
    int size;


    SelectedSelectionKeySet() {
        keys = new SelectionKey[1024];
    }


    @Override
    public boolean add(SelectionKey o) {
        if (o == null) {
            return false;
        }


        keys[size++] = o;
        if (size == keys.length) {
            increaseCapacity();
        }


        return true;
    }
}

从这里我们可以发现, 这个Set集合底层使用的是数组, 调用add方法时直接向数组中添加元素就可以, 时间复杂度O(1).

接下来看下Netty使用反射替换掉那个HashSet

代码语言:javascript
复制
Field selectedKeysField = selectorImplClass.getDeclaredField("selectedKeys");
Field publicSelectedKeysField = selectorImplClass.getDeclaredField("publicSelectedKeys");
          

selectedKeysField.set(unwrappedSelector, selectedKeySet);
publicSelectedKeysField.set(unwrappedSelector, selectedKeySet);

Netty就是通过反射用这个SelectedSelectionKeySet类替换掉了Selector类中的HashSet.

这个地方之所以被Netty搞成这样, 其实还是为了性能. 因为这个地方是涉及数据读写的源头, 如果这个地方的性能不高, 会严重影响到程序的性能. 这也归根结底回到了数据结构的知识.

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2019-10-19,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 Netty历险记 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档