Java游戏服务器开发

Netty零拷贝之CompositeByteBuf实际用法

2020-03-12  本文已影响0人  王广帅

Netty所谓的零拷贝就是在数据序列化操作的时候,尽量减少数据的复制。比如将一个byte[]转化为ByteBuf,如果这样写,就会多一次数据的复制:

        String a = "ccc";
        byte[] bytesSrc = a.getBytes(CharsetUtil.UTF_8);
        ByteBuf byteBuf = Unpooled.buffer();
        byteBuf.writeBytes(bytesSrc);

这里会将byte[]数组中的数据,复制到ByteBuf内部的数组里面。下面这种方式就是零拷贝:

        String a = "ccc";
        byte[] bytesSrc = a.getBytes(CharsetUtil.UTF_8);
        ByteBuf byteBuf = Unpooled.wrappedBuffer(bytesSrc);
        byteBuf.writeBytes(bytesSrc);

这相当于使用已存在的byte[] 数组创建一个ByteBuf,只是对数组有一个引用,ByteBuf的操作,会影响到原来的byte[]。

另外,有时候,如果有两个byte[] 需要转化为一个ByteBuf该怎么办?比如在网络通信中,经常会有Header的ByteBuf和Body的ByteBuf,在发送的时候,需要合成一个ByteBuf。这个时候就该使用CompositeByteBuf,它就像一个容器一样,里面可以包括多个ByteBuf,它是也ByteBuf接口的实现之一。如下面代码所示:

        String a = "ccc";
        String b = "dddd";
        ByteBuf buf1 = Unpooled.wrappedBuffer(a.getBytes(CharsetUtil.UTF_8));
        ByteBuf buf2 = Unpooled.wrappedBuffer(b.getBytes(CharsetUtil.UTF_8));
        ByteBuf compositeByteBuf = Unpooled.wrappedBuffer(buf1,buf2);
     
        int size = compositeByteBuf.readableBytes();
        byte[] bytes = new byte[size];
        compositeByteBuf.readBytes(bytes);
        String value = new String(bytes,CharsetUtil.UTF_8);
        System.out.println("composite buff result : " + value);

如果ByteBuf的数量不确定,还可以这样动态增加ByteBuf:

        String a = "ccc";
        String b = "dddd";
        ByteBuf buf1 = Unpooled.wrappedBuffer(a.getBytes(CharsetUtil.UTF_8));
        ByteBuf buf2 = Unpooled.wrappedBuffer(b.getBytes(CharsetUtil.UTF_8));
        CompositeByteBuf compositeByteBuf = Unpooled.compositeBuffer();
        //compositeByteBuf.addComponent(buf1);//不要使用这个方法,它不会增加writeIndex
        compositeByteBuf.addComponent(true,buf1);//一定要使用这个方法
        if (buf2 != null) {
            compositeByteBuf.addComponent(true, buf2);
        }
       int size = compositeByteBuf.readableBytes();
        byte[] bytes = new byte[size];
        compositeByteBuf.readBytes(bytes);
        
        String value = new String(bytes,CharsetUtil.UTF_8);
        System.out.println("composite buff result : " + value);

这样在对数据操作的时候,实际上并没有对每个ByteBuf的数据进行复制,在最后向网络层发送数据的时候,会一次性从compositeByteBuf中读取所有的数据,只需要拷贝一次即可。


欢迎关注,谢谢打尝
上一篇下一篇

猜你喜欢

热点阅读