美文网首页
Netty CompositeByteBuf 原理

Netty CompositeByteBuf 原理

作者: 绝尘驹 | 来源:发表于2018-10-14 18:08 被阅读0次

    Netty CompositeByteBuf 简介

    CompositeByteBuf 在聚合时使用,多个buffer合并时,不需要copy,通过
    CompositeByteBuf 可以把需要合并的bytebuf 组合起来,对外提供统一的readindex和writerindex

    CompositeByteBuf 里面有个ComponentList,继承ArrayList,聚合的bytebuf都放在ComponentList里面,最小容量为16。

    Component

    compositeByteBuf 的ComponentList 里存的是byteBuf的一个包装类Component,Component 如下:

    private static final class Component {
        final ByteBuf buf;
        final int length;
        int offset;
        int endOffset;
    
        Component(ByteBuf buf) {
            this.buf = buf;
            length = buf.readableBytes();
        }
    
        void freeIfNecessary() {
            buf.release(); // We should not get a NPE here. If so, it must be a bug.
        }
    }
    

    Component 的offset是上一个的endoffset,endoffset是offset+length;

    创建

    CompositeByteBuf content = ctx.alloc().compositeBuffer(maxCumulationBufferComponents);
    

    maxCumulationBufferComponents 是指定ComponentList的大小,这样初始化的CompositeByteBuf的是空的
    ,即writerindex=readerindx=0

    添加ByteBuf

            content.addComponent(true, byteBuf);
    

    添加到CompositeByteBuf 的ComponentList如下,increaseWriterIndex为true,代表更新writerIndex,cIndex为components.size()。

    private int addComponent0(boolean increaseWriterIndex, int cIndex, ByteBuf buffer)    {
        assert buffer != null;
        boolean wasAdded = false;
        try {
            //检查cindex是否超过ComponentList的容量
            checkComponentIndex(cIndex);
    
            int readableBytes = buffer.readableBytes();
    
            // No need to consolidate - just add a component to the list.
            @SuppressWarnings("deprecation")
            //封装为Component,采用大端序
            Component c = new Component(buffer.order(ByteOrder.BIG_ENDIAN).slice());
            //比如第一次聚合的时候,cIndex=0,components.size() = 0;
            if (cIndex == components.size()) {
                wasAdded = components.add(c);
                if (cIndex == 0) {
                    //如果是第一个buffer,则该Component的endOffset为buffer的大小。
                    c.endOffset = readableBytes;
                } else {
                    //如果不是第一个buffer,则该buffer的offset为上一个的endO
                    Component prev = components.get(cIndex - 1);
                    c.offset = prev.endOffset;
                    c.endOffset = c.offset + readableBytes;
                }
            } else {
                components.add(cIndex, c);
                wasAdded = true;
                if (readableBytes != 0) {
                    updateComponentOffsets(cIndex);
                }
            }
            if (increaseWriterIndex) {
                writerIndex(writerIndex() + buffer.readableBytes());
            }
            return cIndex;
        } finally {
            if (!wasAdded) {
                buffer.release();
            }
        }
    }
    

    CompositeByteBuf 扩容

    CompositeByteBuf 在增加新的bytebuf后,会检查CompositeByteBuf的数组components 大小,默认大小是16,即在
    组合了16个bytebuf后,就要扩容了。

    先说下是CompositeByteBuf怎么扩容的,CompositeByteBuf是创建一个新的bytebuf,把数组里的16个bytebuf 写到这个新创建bytebuf里,然后吧数组清空掉,并把新创建的一个大的bytebuf添加到数组里,类似归并的做法,涉及到多次copy,所以尽量不需要扩容。

    扩容的源码如下:

        final int numComponents = components.size();
        if (numComponents > maxNumComponents) {
            final int capacity = components.get(numComponents - 1).endOffset;
            //创建一个大的bytebuf,容量会所有bytebuf的总和。
            ByteBuf consolidated = allocBuffer(capacity);
    
            // We're not using foreach to avoid creating an iterator.
            for (int i = 0; i < numComponents; i ++) {
                Component c = components.get(i);
                ByteBuf b = c.buf;
                //copy c的数据到consolidated
                consolidated.writeBytes(b);
                // 释放c的资源。
                c.freeIfNecessary();
            }
            Component c = new Component(consolidated);
            c.endOffset = c.length;
            components.clear();
            components.add(c);
        }
    }

    相关文章

      网友评论

          本文标题:Netty CompositeByteBuf 原理

          本文链接:https://www.haomeiwen.com/subject/iqktzftx.html