标签: zero-copy

使用和不使用Scatter/Gather操作进行零拷贝

我刚读了一篇解释零拷贝机制的文章.

它讨论了有和没有Scatter/Gather支持的零拷贝之间的区别.

网卡没有SG支持,数据副本如下

在此输入图像描述

NIC支持SG,数据副本如下

在此输入图像描述

总之,使用SG支持的零拷贝可以消除一个CPU拷贝.

我的问题是为什么内核缓冲区中的数据可能会分散?

c linux network-programming linux-kernel zero-copy

6
推荐指数
1
解决办法
5145
查看次数

FileChannel零拷贝传输无法将字节复制到SocketChannel

在Java中使用零拷贝将大文件从文件传输到套接字时,我发现了一些奇怪的行为.我的环境:

  • Windows 7 64位JDK 1.6.0_45和1.7.0_79.
  • Centos 6.6 64位JDK 1.6.0_35

程序的作用:客户端将输入文件复制到套接字中,服务器使用零复制方法将套接字复制到输出文件:transferFrom和transferTo.如果文件大小相对较大,并非所有字节都到达服务器,在Windows情况下为100Mb +,在Centos情况下为2GB +.客户端和服务器驻留在同一台计算机上,localhost地址用于传输数据.

行为因操作系统而异.在Windows上,客户端成功完成transferTo方法.传输的字节数等于输入文件大小.

long bytesTransferred = fileChannel.transferTo(0, inputFile.length(), socketChannel);

另一方面,服务器报告较少的接收字节数.

long transferFromByteCount = fileChannel.transferFrom(socketChannel, 0, inputFile.length());

在Linux上,即使输入文件大小为4Gb,客户端上的传输也是2Gb.两种配置都有足够的空间.

在Windows上,我能够使用以下解决方法之一传输130Mb文件:1)增加服务器上的接收缓冲区大小和2)在客户端中添加线程睡眠方法.这使我认为当所有字节都发送到套接字发送缓冲区而不是服务器时,客户端上的transferTo方法完成.这些字节是否使它成为服务器是不能保证的,这会给我的用例带来问题.

在Linux上,我能够通过单个transferTo调用传输的最大文件大小是2Gb,但至少客户端报告发送到服务器的正确字节数.

我的问题:客户确保将文件保证交付到服务器,跨平台的最佳方式是什么?在Windows上使用什么机制来模拟sendfile()?

这是代码:

客户端 - ZeroCopyClient.java:

import org.apache.commons.io.FileUtils;

import java.io.*;
import java.net.*;
import java.nio.channels.*;

public class ZeroCopyClient {

    public static void main(String[] args) throws IOException, InterruptedException {

        final File inputFile = new File(args[0]);

        FileInputStream fileInputStream = new FileInputStream(inputFile);
        FileChannel fileChannel = fileInputStream.getChannel();
        SocketAddress socketAddress = new InetSocketAddress("localhost", 8083);
        SocketChannel socketChannel = SocketChannel.open(); …
Run Code Online (Sandbox Code Playgroud)

java sockets nio zero-copy

5
推荐指数
1
解决办法
1762
查看次数

有赠品和无赠品的vmsplice(2)的语义是什么?

我试图了解vmsplice(2)syscall 的功能(此处的手册页)。关于SPLICE_F_GIFT标志的作用,我有两个问题:

  1. 手册页指出,一旦将页面赠予内核,就不能再修改内存。这是否意味着该内存将永远固定,还是可能指的是赠礼过程无法映射的虚拟内存,而不是物理内存?换句话说,这种用法的典型用法是什么样的?

  2. 如果我不设置SPLICE_F_GIFT,vmsplice(2)与矢量化写syscall 有什么不同writev(2)吗?

linux linux-kernel splice zero-copy

5
推荐指数
1
解决办法
316
查看次数

如何使用OpenCL以零拷贝方式直接写入Linux帧缓冲区?

我正在使用 OpenCL 进行一些图像处理,并希望使用它将 RGBA 图像直接写入帧缓冲区。工作流程如下图所示:

1) 将帧缓冲区映射到用户空间。

2) 使用 clCreateBuffer 创建 OpenCL 缓冲区,标志为“CL_MEM_ALLOC_HOST_PTR”

3)使用clEnqueueMapBuffer将结果映射到framebuffer。

然而,这不起作用。屏幕上什么也没有。然后我发现帧缓冲区映射的虚拟地址与映射OpenCL的虚拟地址不同。有没有人做过从 GPU 到帧缓冲区的数据零复制移动?我应该使用什么方法来实现此目的有任何帮助吗?

一些关键代码:

if ((fd_fb = open("/dev/fb0", O_RDWR, 0)) < 0) {
    printf("Unable to open /dev/fb0\n");
    return -1;
}
fb0 = (unsigned char *)mmap(0, fb0_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd_fb, 0);
...
cmDevSrc4 = clCreateBuffer(cxGPUContext, CL_MEM_READ_WRITE | CL_MEM_ALLOC_HOST_PTR, sizeof(cl_uchar) * imagesize * 4, NULL, &status);
...
fb0 = (unsigned char*)clEnqueueMapBuffer(cqCommandQueue, cmDevSrc4, CL_TRUE, CL_MAP_READ, 0, sizeof(cl_uchar) * imagesize * 4, 0, NULL, NULL, &ciErr);
Run Code Online (Sandbox Code Playgroud)

framebuffer opencl memory-mapping zero-copy

5
推荐指数
1
解决办法
825
查看次数

Linux splice()返回EINVAL("无效参数")

我正在尝试使用splice(man 2 splice)将数据从UDP套接字直接复制到文件.不幸的是,第一次调用splice()会返回EINVAL.

手册页指出:

EINVAL Target file system doesn't support splicing; target file is opened in
       append mode; neither of the descriptors refers to a pipe; or offset
       given for nonseekable device.
Run Code Online (Sandbox Code Playgroud)

但是,我相信这些条件都不适用.我正在使用Fedora 15(内核2.6.40-4),所以我相信所有文件系统都支持splice().目标文件在第一次调用splice时应该是无关紧要的,但为了完整性我将通过它打开它open(path, O_CREAT | O_WRONLY | O_TRUNC, S_IRUSR | S_IWUSR).两个调用都使用管道,除了NULL之外,两个调用都不使用偏移量.

这是我的示例代码:

int sz = splice(sock_fd, 0, mPipeFds[1], 0, 8192, SPLICE_F_MORE);
if (-1 == sz)
{
int err = errno;
LOG4CXX_ERROR(spLogger, "splice from: " << strerror(err));
return 0;
}

sz = splice(mPipeFds[0], 0, file_fd, 0, …
Run Code Online (Sandbox Code Playgroud)

udp pipe splice zero-copy

4
推荐指数
2
解决办法
2101
查看次数

Linux套接字:零拷贝本地,TCP/IP远程

网络是我操作系统中最糟糕的区域,所以请原谅我提出一个不完整的问题.我已经读了几个小时了,但是我的脑子里有点游泳.(对我而言,与制定网络协议相比,我觉得芯片设计很容易.)

我有一些通过套接字相互通信的网络服务.具体来说,创建套接字fd = socket(PF_INET, SOCK_STREAM, 0);,自动获取TCP/IP.我需要这个作为基本案例,因为这些服务可能在不同的机器上运行.

但对于一个项目,我们试图将它们全部压缩到基于Atom Z530P的功能不足的嵌入式"设备"中,因此在我看来,内存复制开销是我们可以优化的.我在这里一直在阅读:data-link-access-and-zero-copy和Linux_packet_mmap以及packet_mmap.

对于这种情况,可以创建如下的套接字:fd = socket(PF_PACKET, PF_RAW, 0);.还有很多其他事情要做,比如分配环形缓冲区,对它们进行映射,将它们与套接字相关联等等.看起来你只能使用sendto和recvfrom传输数据.据我所知,由于套接字是本地的,你不需要一个可靠的"流"类型套接字,所以原始套接字是适当的接口,我猜测环形缓冲区是以页面粒度使用的,每个数据包(或数据报)从页面边界开始.

在我花费大量时间尝试进一步调查之前,我希望一些有用的人可以帮助我解决一些问题:

  • 我应该从零拷贝套接字中获得多少性能优势?我想最后一次检查,我们从一个进程到另一个进程最多移动到40 MB /秒,最后到磁盘.在最基本的场景中,数据从捕获过程转移到一对多进程(其他人可以监听流),转移到写入磁盘的归档进程.这是两个不计算磁盘和内部东西的啤酒花.
  • Linux是否会自动执行此操作,优化在同一台计算机上运行的进程?
  • 在任何情况下,我都会在TCP端口中监听套接字.我可以使用它们在进程之间建立连接但仍然可以使用零拷贝吗?换句话说,我可以将AF_INET与PF_PACKET一起使用吗?
  • 具有SOCK_RAW的PF_PACKET是零拷贝套接字的唯一有效配置吗?
  • 是否有任何好的示例代码将使用TCP/IP的零拷贝作为后备?
  • 检测两个进程在同一台机器上的最简单或最好的方法是什么?他们知道彼此的IP地址,所以我可以比较并使用不同的代码路径.有更简单的方法吗?
  • 我可以在基于数据包的套接字上使用write()和read(),还是仅对流有效?(重写连接的方式会更简单,然后重写所有套接字代码.)
  • 我是否过度复杂化和/或优化错误的东西?OProfiler告诉我,大多数CPU时间花费在两个地方:(1)zlib,以及(2)内核,我无法分析,因为我使用的是CentOS 6.2,它没有提供vmlinux.我假设内核时间是空闲时间和数据复制的组合,而不是其他.

在此先感谢您的帮助!

sockets linux zero-copy

4
推荐指数
1
解决办法
5898
查看次数

我可以从const char*数组中用C++进行零拷贝std :: string分配吗?

对我的应用程序进行概要分析表明它在字符串分配中花费了近5%的CPU时间.在许多地方,我从64MB字符缓冲区制作C++ std :: string对象.问题是,缓冲区在程序运行期间永远不会改变.我对std::string(const char *buf,size_t buflen)调用的分析是正在复制字符串,因为缓冲区可能在字符串生成后发生变化.这不是问题所在.有没有解决这个问题的方法?

编辑:我正在使用二进制数据,所以我不能只是传递char *s.此外,由于总是扫描NULL,我会有很大的开销,这std::string避免了.

c++ performance stdstring zero-copy

4
推荐指数
2
解决办法
3090
查看次数

如何在POSIX中实现零拷贝机制?

我想在两个进程本地/网络之间共享/传输数据.通用IPC机制共享内存和消息队列可用于传输数据.但这些机制涉及多个副本.

我遇到了零复制机制,这减少了CPU上的复制开销.Linux支持使用sendfile和splice.这些API不在POSIX中.如何仅使用POSIX API实现零拷贝?

linux posix zero-copy

4
推荐指数
1
解决办法
804
查看次数

如何使用已启用Futures的Hyper Chunk的Serde Zero-copy反序列化来存储结果?

我正在使用期货,tokio,hyper和serde_json来请求和反序列化我需要保留的一些数据,直到我的下一个请求.我最初的想法是创建一个包含hyper::Chunk从中借用的反序列化数据的结构Chunk,但却无法使生命周期正确.我尝试使用租赁箱,但我也无法使用它.也许我'buffer在宣布缓冲区之前使用了生命周期Vec,但也许我搞砸了别的东西:

#[rental]
pub struct ChunkJson<T: serde::de::Deserialize<'buffer>> {
    buffer: Vec<u8>,
    json: T
}
Run Code Online (Sandbox Code Playgroud)

有没有办法让生命时间正确,或者我应该使用DeserializeOwned并放弃零拷贝?

有关更多上下文,以下代码可以正常工作(定期从两个URL反序列化JSON,保留结果,以便我们可以对它们执行某些操作).我想改变我的X和Y类型Cow<'a, str>用于他们的领域,从改变DeserializeOwned为Deserialize<'a>.为此,我需要存储已经反序列化的切片,但我不知道如何做到这一点.我正在寻找使用Serde的零拷贝反序列化并保留结果的示例,或者用于重构我的代码的一些想法.

#[macro_use]
extern crate serde_derive;

extern crate serde;
extern crate serde_json;
extern crate futures;
extern crate tokio_core;
extern crate tokio_periodic;
extern crate hyper;

use std::collections::HashMap;
use std::error::Error;

use futures::future;
use futures::Future;
use futures::stream::Stream;
use hyper::Client;


fn stream_json<'a, T: serde::de::DeserializeOwned + Send + 'a>
    (handle: …
Run Code Online (Sandbox Code Playgroud)

rust zero-copy serde

4
推荐指数
1
解决办法
931
查看次数

如何通过 Spring-Feign 获取 InputStream?

我想通过 Spring-OpenFeign 从服务器下载一个文件并将其保存在本地目录中,并使用零拷贝。

简单的下载方法如下:

import org.apache.commons.io.FileUtils

@GetMapping("/api/v1/files")
ResponseEntity<byte[]> getFile(@RequestParam(value = "key") String key) {
    ResponseEntity<byte[]> resp = getFile("filename.txt")
    File fs = new File("/opt/test")
    FileUtils.write(file, resp.getBody())
}
Run Code Online (Sandbox Code Playgroud)

在这段代码中,数据流将是这样的 feign Internal Stream -> Buffer -> ByteArray -> Buffer -> File

如何高效快速地下载和保存文件内存?

java zero-copy spring-boot spring-cloud-feign feign

4
推荐指数
1
解决办法
3080
查看次数