很早就知道sendfile这个专门用来传输大文件的函数,也称为零拷贝,但一直没测试过,今天用了宿舍的网和小组内的网测试了下,发现结果和我预想的不一样。


为什么效率高,网上说的也很多了,看下man手册中的内容
sendfile() copies data between one file descriptor and another. Because this copying is done within the kernel, sendfile() is more efficient than the combination of read(2) and write(2), which would require transferring data to and from user space.
普通的read和write先会将数据拷贝到用户空间,然后再拷贝到内核空间,然后从tcp缓冲区发送出去。sendfile避免了多余的拷贝。


测试过程:

通过hdparm -Tt /dev/sda
测试了我的磁盘IO大约是110MB/sec

通过bmon
宿舍网大概150k/s,小组内网大概4.5~5.5MB/s。
只是测试了个大概。参考而已

服务端跑在学长借我的服务器上测试。


数据有限,我测试的分别为7.5M,90M,2G的数据。
起初宿舍网络有点慢,read,write版本和sendfile版本运行出来的时间都几乎差不多。然后我在小组测试网速4.5~5.5MB/s,跑出来的数据竟然也差不多,有时read,write版本竟然比sendfile版本的时间短
很奇怪,最后一想,磁盘IO的性能依然是远大于网络IO的性能,我测试的两种网络带宽远远不够。


测试结论:

最后询问了学长,得知4.5mb/s-5.5mb/s也就是带宽为36-44mib/s的网络IO是远远不够的,用ifconfig查看本机ip来测试,本机千兆网卡测试出来传送2.2G数据sendfile效率的确高于read,write。
那么像我们普通这种网络带宽根本不能满足且突出sendfile的性能。


测试代码:客户端

客户端两个版本,一个为read,write,一个为sendfile,修改注释即可

#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <sys/sendfile.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>int main(int argc, char *argv[])
{if(argc < 3){printf("argument error\n");exit(1);}char *ip = argv[1];int port = atoi(argv[2]);struct sockaddr_in server;server.sin_family = AF_INET;server.sin_port = htons(port);inet_pton(AF_INET, ip, &server.sin_addr);int fd = socket(AF_INET, SOCK_STREAM, 0);if(fd < 0){printf("create socket error\n");exit(1);}int con_ret = connect(fd, (struct sockaddr*)&server, sizeof(server));if(con_ret == -1){printf("connect error\n");exit(1);}char *name = argv[3];int r_fd = open(name, O_RDONLY);if(r_fd == -1){printf("open file error\n");exit(1);}struct stat st;long int size = stat(name, &st);if(size < 0){printf("file stat error\n");exit(1);}printf("file size:%ld\n", st.st_size);off_t pos = lseek(r_fd, 0, SEEK_SET);if(pos < 0){printf("obtain fileP error\n");exit(1);}char *cname = "newfile";int sn = send(fd, cname, sizeof(argv[3]), 0);struct timeval startTime, endTime;double timeuse;gettimeofday(&startTime, NULL);//sendfile测试版本//int n = sendfile(fd, r_fd, &pos, st.st_size);long int ssize = 0;char buffer[2048];long int n = 0;//read,write测试版本while(1){bzero(buffer, 2048);int rn = read(r_fd, buffer, 2048);int wn = write(fd, buffer, 2048);if(n >= st.st_size){printf("size:%ld\n", n);printf("size:%ld\n", st.st_size);break;}n += rn;}gettimeofday(&endTime, NULL);timeuse = 1000000*(endTime.tv_sec - startTime.tv_sec) + (endTime.tv_usec - startTime.tv_usec);timeuse /= 1000000;printf("timeuse = %lf\n", timeuse);if(n == -1){printf("send file error\n");exit(1);}return EXIT_SUCCESS;
}

测试代码:服务器

服务端测试代码不变

#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <fcntl.h>
#include <string.h>int main(int argc, char *argv[])
{if(argc < 2){printf("argument error\n");exit(1);}char *ip = argv[1];int port = atoi(argv[2]);struct sockaddr_in server;server.sin_family = AF_INET;server.sin_port = htons(port);inet_pton(AF_INET, ip, &server.sin_addr);int fd = socket(AF_INET, SOCK_STREAM, 0);if(fd < 0){printf("create socket error\n");exit(1);}int b_ret = bind(fd, (struct sockaddr*)&server, sizeof(server));if(b_ret == -1){printf("bind error\n");exit(1);}int l_ret = listen(fd, 64);if(l_ret == -1){printf("listen error\n");exit(1);}socklen_t len = sizeof(server);int sockfd = accept(fd, (struct sockaddr*)&server, &len);if(sockfd == -1){printf("accept error\n");exit(1);}else{printf("connect success\n");}char name[128];char buffer[2048];bzero(name, 128);bzero(buffer, 2048);int n = recv(sockfd, name, 2048, 0);if(n <= 0){printf("recv error\n");exit(1);}printf("name:%s\n", name);int w_fd = open(name, O_WRONLY | O_CREAT, 777);if(w_fd == -1){printf("open file error\n");exit(1);}off_t pos = lseek(w_fd, 0, SEEK_CUR);if(pos < 0){printf("obtain file pointer error\n");exit(1);}while(1){bzero(buffer, 2048);int n = recv(sockfd, buffer, 2048, 0);if(n < 0){printf("recv error\n");exit(1);}else if(n == 0){break;}ssize_t s_t = write(w_fd, buffer, n);if(s_t < 0){printf("write error\n");exit(1);}}printf("recv file success!!!\n");return EXIT_SUCCESS;
}

初探sendfile相关推荐

  1. 2021年大数据Flink(九):Flink原理初探

    Flink原理初探 Flink角色分工 在实际生产中,Flink 都是以集群在运行,在运行的过程中包含了两类进程. JobManager: 它扮演的是集群管理者的角色,负责调度任务.协调 checkp ...

  2. 从壹开始微服务 [ DDD ] 之一 ║ D3模式设计初探 与 我的计划书

    缘起 哈喽大家周四好!又是开心的一天,时间过的真快,我们的 <从壹开始 .net core 2.1 + vue 2.5 >前后端分离系列共 34 篇已经完结了,当然以后肯定还会有更新和修改 ...

  3. 经典算法研究系列:二、Dijkstra 算法初探

    经典算法研究系列:二.Dijkstra 算法初探  July   二零一一年一月 ====================== 本文主要参考:算法导论 第二版.维基百科. 写的不好之处,还望见谅. 本 ...

  4. las格式测井曲线_邹榕,等:顺北和托甫台区块奥陶系断裂结构单元测井响应特征初探...

    引用格式:邹榕,徐中祥,张晓明,等.顺北和托甫台区块奥陶系断裂结构单测井响应特征初探[J].油气藏评价与开发,2020,10(2):18-23.ZOUR, XU Z X, ZHANG X M, et ...

  5. 2018-4-15摘录笔记,《网络表征学习前沿与实践》 崔鹏以及《网络表征学习中的基本问题初探》 王啸 崔鹏 朱文武

    1.来源:<网络表征学习前沿与实践>  崔鹏 (1)随着数据的增加以及计算机计算速度的增加,想当然的以为速度快了,数据再多也是可以自己算的,但是若是数据之间存在着复杂的关系,那么处理一个样 ...

  6. python argparse_Python 命令行之旅:初探 argparse

    本文首发于 HelloGitHub 公众号,并发表于 Prodesire 博客. 前言 你是否好奇过在命令行中敲入一段命令后,它是如何被解析执行的?是否考虑过由自己实现一个命令行工具,帮你执行和处理任 ...

  7. HTML5+MUI+HBuilder 之初探情人

    07,08年那会儿正当Java火爆,C/C++仍是广泛运用的一门语言的时候,所以我的大学都献给了C/C++和Java.当诺基亚的倒闭成为按键机时代衰落的标志时,移动APP的开发也如破堤之洪.爆炸式的崛 ...

  8. 使用Mahout搭建推荐系统之入门篇3-Mahout源码初探

    2019独角兽企业重金招聘Python工程师标准>>> 用意: 希望了解Mahout中数据的存储方式, 它如何避免java object带来的冗余开销.学完知识,要进行些实战 去分析 ...

  9. 使用sendfile()让数据传输得到最优化,TCP_CORK、TCP_DEFER_ACCEPT和TCP_QUICKACK优化网络...

    当今国互联网的飞速发展让人们获益匪浅,同时人们对于互联网 的期望值也变得越来越高.这就形成了一个矛盾,虽然互联网的 发展已经是相当迅猛的了,但是人们还是期望从服务器到客户终 端的文件传输的速度能够比现 ...

最新文章

  1. 侧链,驱动链,和根链的双向锚定设计
  2. MySQL 数据库常用命令
  3. ad放置网络标号_PCB工程师必备:AD常用快捷键总结,超级实用
  4. luogu P1027 Car的旅行路线
  5. 085_html5服务器发送事件
  6. 音频开发中常见的四个错误
  7. RealNetworks CTO:我们追求低复杂度的软解码
  8. php 数据导出到excel文件,PHP导出数据到excel文件
  9. 29.3 用户模式构造
  10. 我和面试官的博弈:Redis 篇
  11. xen服务器不能挂载iso文件,Citrix XenCenter安装VM之挂载ISO详解
  12. 亚马逊alexa智能家电_如何使用Amazon Alexa轻松设置智能家居设备
  13. linux libyuv 编译,编译libyuv
  14. 荣耀手机环比倍增,小米有点受伤
  15. 计算机学霸小黄是谁,人人网惊现“小黄鸡”火成一片 大学生调侃“你是学霸派来的么?”...
  16. 9527风先生的文章《Ubuntu20.04配置ORBSLAM2并运行》 :验证是能走通的
  17. python竞赛猜名次_五人预测比赛结果均答对一半,求比赛名次
  18. labuladong的算法小抄_学会了回溯算法,我终于会做数独了
  19. swift锁屏播放,音乐进度更新,专辑,歌手名显示
  20. 基于MVS的三维重建算法学习笔记(二)— 立体视觉的几何基础总结

热门文章

  1. mysql日期隐式转换_MySQL 隐式转换 | 剑花烟雨江南
  2. 在服务端没接显示器的情况下,nomachine远程连接客户端看到的是黑屏的问题
  3. JavaScript 16进制转10进制
  4. redis3.2.100在windows不支持daemonize命令后台启动
  5. android xwalkview 截屏,如何在Cordova中为你的应用创建屏幕截图
  6. webView网页自适应屏幕
  7. Pytorch LSTM 代码解读及自定义双向 LSTM 算子
  8. 金田一动画所有OP ED的列表
  9. 微信小程序:消息提示框(wx.showToast)和 交互提示框(wx.showModal)
  10. Oracle处理CLOB超过4000入库问题 (2)