将大数据写入套接字时最小化副本

2024-01-05

我正在编写一个处理图像(大数据)的应用程序服务器。在将图像数据发送回客户端时,我试图尽量减少副本。我需要发送给客户端的处理后的图像位于从 jemalloc 获得的缓冲区中。我想到的将数据发送回客户端的方式是:

1)简单的写调用。

// Allocate buffer buf.
// Store image data in this buffer.
write(socket, buf, len);

2)我通过 mmap 而不是 jemalloc 获取缓冲区,尽管我认为 jemalloc 已经使用 mmap 创建了缓冲区。然后我进行一个简单的调用 write。

buf = mmap(file, len);  // Imagine proper options.
// Store image data in this buffer.
write(socket, buf, len);

3)我像以前一样通过mmap获取缓冲区。然后我使用 sendfile 发送数据:

buf = mmap(in_fd, len);  // Imagine proper options.
// Store image data in this buffer.
int rc;
rc = sendfile(out_fd, file, &offset, count);
// Deal with rc.

鉴于 jemalloc 可能首先通过 mmap 分配内存,看起来 (1) 和 (2) 可能会做同样的事情。不过我不确定(3)。这真的会带来任何好处吗?图4就这个article http://www.linuxjournal.com/article/6345?page=0,1在 Linux 上,零复制方法表明可以使用 sendfile 来阻止进一步的复制:

没有数据复制到套接字缓冲区中。相反,只有描述符 有关数据的位置和长度的信息是 附加到套接字缓冲区。 DMA引擎直接传递数据 来自内核缓冲区到协议引擎,从而消除 剩余的最终副本。

如果一切顺利的话,这似乎是一场胜利。我不知道我的映射缓冲区是否算作内核缓冲区。我也不知道什么时候重新使用这个缓冲区是安全的。由于 fd 和长度是附加到套接字缓冲区的唯一内容,因此我假设内核实际上将此数据异步写入套接字。如果确实如此,sendfile 的返回意味着什么?我如何知道何时重新使用该缓冲区?

所以我的问题是:

  1. 将大缓冲区(在我的例子中是图像)写入套接字的最快方法是什么?图像保存在内存中。
  2. 在映射文件上调用 sendfile 是个好主意吗?如果是,有什么问题吗?这会带来任何胜利吗?

看来我的怀疑是正确的。我从中得到了我的信息article https://systemsnotes.wordpress.com/2013/03/24/sendfile-on-memory-mapped-files/。引用其中:

此外,这些网络写入系统调用(包括 sendfile)可能并且 在许多情况下,确实会在该方法通过 TCP 发送数据之前返回 呼叫已被确认。这些方法一旦所有数据就返回 被写入套接字缓冲区(sk buff)并被推送到 TCP 写队列,TCP 引擎可以从那时起单独管理。在 换句话说,sendfile 返回的最后一个 TCP 发送窗口是 实际上没有发送到远程主机,而是排队。在以下情况下 支持分散-聚集 DMA,没有单独的缓冲区 保存这些字节,而不是缓冲区(sk buffs)只保存指向 操作系统缓冲区高速缓存的页面,文件内容所在的位置。 如果我们修改内容,这可能会导致竞争条件 与最后一个 TCP 发送窗口中的数据相对应的文件 返回发送文件。因此 TCP 引擎可能会发送新写入的 数据传输到远程主机,而不是我们最初想要的 发送。

假设映射文件中的缓冲区甚至被认为是“DMA-able”,似乎没有办法知道何时可以安全地重新使用它,而无需来自实际客户端的明确确认(通过网络)。我可能不得不坚持简单的写入调用并产生额外的副本。有一个paper https://systemsnotes.files.wordpress.com/2013/03/paper.pdf(也来自文章)有更多细节。

Edit: This article http://ogris.de/howtos/splice.html在拼接调用上也显示出问题。引用它:

请注意,将数据从 mmap 缓冲区拼接到网络时 套接字,不可能说出所有数据何时已发送。即使 splice() 返回时,网络堆栈可能尚未发送所有数据。所以 重用缓冲区可能会覆盖未发送的数据。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

将大数据写入套接字时最小化副本 的相关文章

随机推荐

  • 如何在 Makefile 中获取脚本源?

    有没有更好的方法从 makefile 中获取设置环境变量的脚本 FLAG 0 ifeq FLAG 0 export FLAG 1 bin myshell c
  • 递归取消引用指针

    当我试图在这里回答一个问题时 我发现了这个问题 如何递归取消引用指针 C 03 https stackoverflow com questions 8022821 how to recursively dereference pointer
  • 跨两个表的 SQL SELECT

    我对如何处理这个 SQL 查询有点困惑 我有两个表 记录数相同 我想返回一个列 该列是两者之间的除法 换句话说 这是我的无法正常工作 query SELECT SELECT v FROM Table1 SELECT DotProduct F
  • 升级到 NDK 14 后无法在 C++ 代码中找到声明

    我更新了 Android Studio 2 3 以使用 NDK 14 当您使用代码时 一切都按预期工作 代码编译并且应用程序按预期运行 然而 由于某种原因 当您尝试跳转到任何 C 对象 函数 变量的减速时 您会收到一条消息 工作室 无论代码
  • 如何在服务器发布操作结果后打开新选项卡

    情况是这样的 我有一个保存和一个打印按钮
  • 在php中将数字转换为字符串

    在下面我尝试过 code string code 没有成功 如何在 PHP 中将数字转换为字符串 code 087326487326 strlen strlen code print strlen br for i strlen i gt
  • python列表循环技术语法[重复]

    这个问题在这里已经有答案了 我正在读一本article http www peterbe com plog uniqifiers benchmark关于 python 删除列表中的重复元素 有一个函数定义为 def f8 seq Dave
  • 将 unique_ptr 与成员函数指针一起使用时出错

    我有一堂课如下 class A public A int key m key key int Key const return m key private int m key 我测试使用 unique ptr 和成员函数指针 int A M
  • SwiftUI TabBar:点击当前选定选项卡的 TabItem 来重置视图的操作

    我正在开发的应用程序基于 TabBar 当我在选项卡上时 我希望能够再次单击 tabItem 来重置视图 类似于 Twitter 在其 tabBar 中的做法 但我不知道如何识别该操作 向 TabItem 添加按钮不起作用 添加 ontap
  • MATLAB 图形在插入 LaTeX 时不具有相同的大小(尽管使用相同的代码生成)

    我正在 MATLAB 中生成一些图形 并尝试将它们插入到 LaTeX 中 然而 当我这样做时 它们通常没有相同的大小 尽管我使用相同的设置来生成它们 例如 我当前使用的 MATLAB 代码是这个 lsize 16 Label fontsiz
  • 如何使用“kubectl patch --type='json'”更新秘密

    我创建了一个这样的秘密 kubectl create secret generic test from literal username testuser from literal password 12345 我想将用户名更新为testu
  • 如何为 msbuild.exe 指定其他包含目录

    我正在尝试安装 nodejs 模块 ibm db 我遇到的问题是 为了安装此模块 node gyp 需要使用 msbuild 构建它 但它不会检测我已安装的一些头文件 如何将附加头文件的目录添加到某个路径 以便 msbuild exe 在尝
  • 识别字符串中的特殊非字母数字字符

    我正在研究密码验证 该验证应该只允许 a z 0 9 和这些字符 lt gt 我尝试使用正则表达式 但我不太擅长使用它们 而且我不确定这是否可能 或者我是否没有转义正确的字符 var allowedCharacters A Za Z0 9
  • VTKCamera焦点和位置的差异

    我正在使用 vtkCamera 并尝试移动它并使其看起来在某个点 例如 如果我想把相机放在 x y z 并让它看看 0 0 0 例如 使用 openGL 中的 gluLookAt 我们会将眼睛坐标设置为 x y z 和中心坐标 0 0 0
  • Angular 6服务注入Interceptor后未定义

    我找不到任何方法来注入我的认证服务 inside 错误处理拦截器 它返回给我一个 不明确的 注入后的对象 否则会抛出错误 这是我的错误处理拦截器 import Injectable from angular core import Auth
  • 为列表列表中的每个列表创建单独的 Counter() 对象和 Pandas DataFrame

    我能找到的所有其他答案都专门提到了在列表列表中聚合所有嵌套列表 而我希望为每个列表单独聚合 我目前有一个列表列表 master list a a b b b c c c d d d a a a c c c c c c a a f f f 我
  • Netbeans 中的 Arduino(处理)库和控制

    我正在尝试控制 4 个 LED 并从 4 个触点获取模拟输入 该程序是用java编写的 因此要访问arduino的功能 例如AnalogRead 和将LED设置为高或低 导入处理库可以让程序使用这些功能吗 我还想知道 如果程序会自行传输到a
  • Durandal 登录页面重定向模式

    TL DR要求用户登录才能查看 Durandal 单页面应用程序 SPA 中的某些页面的好模式是什么 我需要一个系统 如果用户尝试导航到需要登录的 页面 他们会被重定向到登录页面 在此登录页面上成功进行身份验证后 我希望应用程序将它们重定向
  • XSLT 默认模板混淆

    我对 XSLT 处理器节点的方式感到困惑 假设我有一个像这样的 XML 文档
  • 将大数据写入套接字时最小化副本

    我正在编写一个处理图像 大数据 的应用程序服务器 在将图像数据发送回客户端时 我试图尽量减少副本 我需要发送给客户端的处理后的图像位于从 jemalloc 获得的缓冲区中 我想到的将数据发送回客户端的方式是 1 简单的写调用 Allocat