Java 零拷贝_java clone 深拷贝

Java 零拷贝_java clone 深拷贝Java零拷贝参考:Java中的零拷贝零拷贝(英语:Zero-copy)技术是指计算机执行操作时,CPU不需要先将数据从某处内存复制到另一个特定区域。这种技术通常用于通过网络传输文件时节省CPU周期和内存带宽。零拷贝技术可以减少数据拷贝和共享总线操作的次数,消除传输数据在存储器之间不必要的中间拷贝次数,从而有效地提高数据传输效率零拷贝技术减少了用户进程地址空间和内核地址空间之间因为上:下文切换而带来的开销传统的IO数据读写如下的例子,Java传统IO和网络编程的一段代码Fi

大家好,又见面了,我是你们的朋友全栈君。如果您正在找激活码,请点击查看最新教程,关注关注公众号 “全栈程序员社区” 获取激活教程,可能之前旧版本教程已经失效.最新Idea2022.1教程亲测有效,一键激活。

Jetbrains全系列IDE使用 1年只要46元 售后保障 童叟无欺

Java 零拷贝

参考:

零拷贝(英语: Zero-copy) 技术是指计算机执行操作时,CPU不需要先将数据从某处内存复制到另一个特定区域。这种技术通常用于通过网络传输文件时节省CPU周期和内存带宽。

  • 零拷贝技术可以减少数据拷贝和共享总线操作的次数,消除传输数据在存储器之间不必要的中间拷贝次数,从而有效地提高数据传输效率
  • 零拷贝技术减少了用户进程地址空间和内核地址空间之间因为上:下文切换而带来的开销

传统的IO数据读写
如下的例子,Java传统IO和网络编程的一段代码

File file = new File("test.txt");
RandomAccessFile raf = new RandomAccessFile(file, "rw");
byte[] arr = new byte[(int) file.length()];
raf.read(arr);
Socket socket = new ServerSocket(8090).accept();
socket.getOutputStream().write(arr);

实际上就是一个文件读和文件写的过程
传统IO读写示意图
传统IO读写示意图
1.DMA(Direct Memory Access,直接内存拷贝,即经过CPU的拷贝)等待数据准备好,把磁盘数据读取到操作系统内核缓冲区;
2.用户进程,将内核缓冲区的数据copy到用户空间。
3.读取文件,再用socket发送出去,再将用户空间的数据copy到socket网络发送缓冲区(属于操作系统内核的缓冲区);
4.将socket buffer的数据,copy到网卡,由网卡进行网络传输。

传统的IO进行了4次拷贝,进行了3次上下文切换。4次拷贝,其中两次是DMA copy,两次是CPU copy

mmap优化
mmap通过内存映射,将文件映射到内核缓冲区,同时,用户空间可以共享内核空间的数据。这样,在进行网络传输时,就可以减少内核空间到用户控件的拷贝次数

mmap优化

这种方式的I/O原理就是将用户缓冲区(user buffer)的内存地址和内核缓冲区(kernel buffer)的内存地址做一个映射,也就是说系统在用户态可以直接读取并操作内核空间的数据。

可见使用mmap进行IO,进行了3次拷贝,进行了3次上下文切换

Linux支持的零拷贝

1.sendfile
linux 2.1支持的sendfile

当调用sendfile()时,DMA将磁盘数据复制到kernel buffer,然后将内核中的kernel buffer直接拷贝到socket buffer;
一旦数据全都拷贝到socket buffer,sendfile()系统调用将会return、代表数据转化的完成。
socket buffer里的数据就能在网络传输了。

sendfile
sendfile会经历:3次拷贝,1次CPU copy 2次DMA copy,以及2次上下文切换

提示 – 零拷贝是从操作系统角度来看的,是指没有CPU拷贝

Linux在2.4版本中,做了一些修改,避免了从内核缓冲区拷贝到Socket buffer的操作,直接拷贝到协议栈,从而减少了一次数据拷贝
在这里插入图片描述
会经历2次拷贝: 0次cpu copy,2次DMA copy

mmap和sendFile的区别
1.mmap适合小数据量读写,sendFile适合大文件传输
2.mmap需要4次上下文切换,3次数据拷贝;sendFile需要3次上下文切换,最少2次数据拷贝
3.sendFile可以利用DMA放肆,减少CPU拷贝,mmap则不能(必须从内核拷贝到Socket缓冲区)

传统方式

如下的服务端OldIOServer

public class OldIOServer { 
   
    public static void main(String[] args) throws Exception { 
   
        ServerSocket serverSocket = new ServerSocket(7001);
        while (true) { 
   
            Socket socket = serverSocket.accept();
            DataInputStream dataInputStream = new DataInputStream(socket.getInputStream());

            try { 
   
                byte[] byteArray = new byte[4096];
                while (true) { 
   
                    int readCount = dataInputStream.read(byteArray, 0, byteArray.length);
                    if (readCount == -1) { 
   
                        break;
                    }
                }
            } catch (Exception e) { 
   
                e.printStackTrace();
            }
        }
    }
}

客户端OldIOClient

public class OldIOClient { 
   
    public static void main(String[] args) throws Exception{ 
   

        Socket socket = new Socket("localhost", 7001);

        String fileName = "test.txt";
        InputStream inputStream = new FileInputStream(fileName);

        DataOutputStream dataOutputStream = new DataOutputStream(socket.getOutputStream());

        byte[] buffer = new byte[4096];
        long readCount;
        long total = 0;

        long startTime = System.currentTimeMillis();

        while ((readCount = inputStream.read(buffer)) >= 0) { 
   
            total += readCount;
            dataOutputStream.write(buffer);
        }

        System.out.println("发送总字节数:" + total + ", 耗时:" + (System.currentTimeMillis() - startTime));

        dataOutputStream.close();
        socket.close();
        inputStream.close();

    }
}

发送的test.txt文件内容如下:
01
控制台输出如下:
02

NIO方式

服务端:

public class NewIOServer { 
   
    public static void main(String[] args) throws Exception{ 
   

        InetSocketAddress address = new InetSocketAddress(7001);

        ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
        ServerSocket serverSocket = serverSocketChannel.socket();
        serverSocket.bind(address);

        ByteBuffer byteBuffer = ByteBuffer.allocate(4096);
        while (true) { 
   
            SocketChannel socketChannel = serverSocketChannel.accept();
            int readCount = 0;
            while (readCount != -1) { 
   
                try { 
   
                    readCount = socketChannel.read(byteBuffer);

                } catch (Exception ex) { 
   
                    ex.printStackTrace();
                }
                //将buffer倒带
                byteBuffer.rewind();
            }
        }

    }
}

客户端:

public class NewIOClient { 
   
    public static void main(String[] args) throws Exception { 
   

        SocketChannel socketChannel = SocketChannel.open();
        socketChannel.connect(new InetSocketAddress("localhost", 7001));
        String fileName = "test.txt";

        //得到一个文件channel
        FileChannel fileChannel = new FileInputStream(fileName).getChannel();
        //准备发送
        long startTime = System.currentTimeMillis();
        //transferTo底层使用零拷贝
        /** * This method is potentially much more efficient than a simple loop that reads from this channel and writes to the target channel. * Many operating systems can transfer bytes directly from the filesystem cache to the target channel without actually copying them */
        long transferCount = fileChannel.transferTo(0, fileChannel.size(), socketChannel);

        System.out.println("发送总字节数:" + transferCount + ", 耗时:" + (System.currentTimeMillis() - startTime));
        fileChannel.close();

    }
}

控制台输出如下,因为我这里传输的文件比较小,所以没什么效果:
03

BIO、NIO、AIO的比较

BIO NIO AIO
IO模型 同步阻塞 同步非阻塞(多路复用) 异步非阻塞
编程难度 简单 复杂 复杂
可靠性
吞吐量

1.同步阻塞:到理发店理发,一直等待理发师,直到轮到自己
2.同步非阻塞:到理发店理发,发现前面有其它人理发,给理发师说下,先干其它的事情,一会儿过来看是否轮到自己
3.异步非阻塞:给理发师打电话,让理发师上门服务,自己干其它事情,理发师自己来给你理发

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/191158.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • 制作initramfs镜像_原版镜像和引导镜像

    制作initramfs镜像_原版镜像和引导镜像Linuxkernel在自身初始化完成之后,需要能够找到并运行第一个用户程序(这个程序通常叫做“init”程序)。用户程序存在于文件系统之中,因此,内核必须找到并挂载一个文件系统才可以成功完成系统的引导过程。在grub中提供了一个选项“root=”用来指定第一个文件系统,但随着硬件的发展,很多情况下这个文件系统也许是存放在USB设备,SCSI设备等等多种多样的设备之上,如果需要正确引导,US

    2022年8月11日
    6
  • Hadoop大数据面试–Hadoop篇

    Hadoop大数据面试–Hadoop篇

  • sql语句快速清空表

    sql语句快速清空表对于sql清空表有三种清空方式1.delete——是逐行删除速度极慢,不适合大量数据删除2.truncate—-删除所有数据,保留表结构,不能撤消还原3.drop——–删除表,数据和表结构一起删除,快速但是在实践过程中我发现,1,2这两种方法在处理大量数据的时候都比较慢,往往要等待许久才能清空完成。所以我考虑还有没有其他的方法达到清空表的作用呢。后来我从导出表结构中…

    2022年5月5日
    125
  • js定义点击事件_回字四种写法

    js定义点击事件_回字四种写法嵌入式点击按钮脚本模型btn.onclick=function(){}W3C事件写法添加事件:appEventListener(事件名,事件函数,false)btn.addEventLi

    2022年8月5日
    2
  • AD PCBlayout 总结[通俗易懂]

    AD PCBlayout 总结[通俗易懂]PCBlayout总结1、关于规则注:多个规则存在时需要设置规则的优先级,如:(1)poly和keepout之间的clearance规则定义2、关于走线拐角PCB走线中不能出现锐角和直角,而且走线也不能和IC的PIN脚垂直首先不光是天线的布线不走锐角,在布线中最好都不走锐角,只是天线的布线尤为重要。1、对于高频电流来说,当导线的拐弯处呈现直角甚至锐角时,在靠近弯角的部位,磁通密度及电场强度都比较高,会辐射较强的电磁波,而且…

    2025年7月4日
    0
  • 《前端运维》一、Linux基础–11服务

    首先服务的概念,对于linux服务器来说,其中大多数的软件都算是服务,比如nginx、mysql、Jenkins等等。下面我们就来学习一下linux中有关服务的一些内容。一、服务简介和分类1、运行

    2022年3月25日
    32

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号