很早就知道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. skyline三维模型规格
  2. pandas最大的时间间隔_pandas计算最大连续间隔的方法
  3. VMware Fusion虚拟机的低分辨率问题(亲测有效)
  4. IOS 开发 UIProgress 和 UISlidre 进度条和滑动条组件
  5. Javascript交互式金融股票基金图表JavaScript Stock Chart
  6. element-ui的confirm里面可一写html
  7. 大数据技术如何有效阻击网络黑产?
  8. 成功必须靠自己去争取。
  9. 《数据结构与算法》实验:排序算法实验比较——选择排序 堆排序
  10. YMEC8A2TB3A2C3
  11. 11. 盛最多水的容器(java实现)--2种解法(左右夹逼,暴力)LeetCode
  12. MT6750处理器资料介绍
  13. 用CNN实现全景图像语义分割!
  14. 网站顶部的跑马灯特效代码
  15. PHP防伪防串货溯源系统源码
  16. 兄弟连社团——全国最大的PHP技术社团
  17. 软件工程——数据流图练习
  18. GPS定位系统源码,GPSBDpro远程视频监控,实时视频+实时定位
  19. Vue中使用vue-codemirror插件实现代码在线编辑
  20. mysql 最近15天,Mysql查询今日/昨天/15天前/上个月/去年/上周每日等函数

热门文章

  1. 设计静电保护所需要的理论基础(ESD保护理论基础)转载自集成电路版图设计公众号
  2. 北京易通宝网络科技有限公司
  3. JavaScript的隐式转换
  4. 如何修改静态IP地址
  5. 关于Atom无法下载插件的问题
  6. DEDE fck编辑器插件 图片排版 自动排版 繁简转换
  7. 同志们有福了,连火车都有wifi了
  8. c++ 可变数组使用
  9. python numpy sum函数_如何使用Python中的sum函数?
  10. Mybatis与Spring集成(易百教程)