![Linux下消息队列和socket绝对速度比拼[转].docx_第1页](http://file1.renrendoc.com/fileroot_temp2/2020-3/20/03226bc7-567d-48c0-8744-5f39e6ad3a9f/03226bc7-567d-48c0-8744-5f39e6ad3a9f1.gif)
![Linux下消息队列和socket绝对速度比拼[转].docx_第2页](http://file1.renrendoc.com/fileroot_temp2/2020-3/20/03226bc7-567d-48c0-8744-5f39e6ad3a9f/03226bc7-567d-48c0-8744-5f39e6ad3a9f2.gif)
![Linux下消息队列和socket绝对速度比拼[转].docx_第3页](http://file1.renrendoc.com/fileroot_temp2/2020-3/20/03226bc7-567d-48c0-8744-5f39e6ad3a9f/03226bc7-567d-48c0-8744-5f39e6ad3a9f3.gif)
![Linux下消息队列和socket绝对速度比拼[转].docx_第4页](http://file1.renrendoc.com/fileroot_temp2/2020-3/20/03226bc7-567d-48c0-8744-5f39e6ad3a9f/03226bc7-567d-48c0-8744-5f39e6ad3a9f4.gif)
![Linux下消息队列和socket绝对速度比拼[转].docx_第5页](http://file1.renrendoc.com/fileroot_temp2/2020-3/20/03226bc7-567d-48c0-8744-5f39e6ad3a9f/03226bc7-567d-48c0-8744-5f39e6ad3a9f5.gif)
已阅读5页,还剩8页未读, 继续免费阅读
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
在当今的网络时代,我们常常见到的进程间通信方式都是socket,比如Java的EJB调用,Java和C通信,Web Service服务等。socket是最常用的通讯技术,几乎所有的系统、语言都支持,socket也是面向网络的,通信的两方可以跨越IP网络进行传输。在本地通信中(同一台机器上的进程间通讯),socket的网络特性却成了累赘,组装解析网络报头、报文确认、CRC校验等都是针对网络的,本地通信没有必要,反而会影响传输效率。本地通信的一些传统技术,如管道、FIFO、消息队列等,没有网络功能的负担,传输速度应该高于socket,那到底高多少以至于值得在应用中替换socket技术呢,今天就来一场小测试,就System V消息队列和socket之间,做一次全面的速度比拼。比拼场地本人的笔记本:赛扬1.5G 内存1.5G系统:Ubuntu8.04 Desktop (Linux 2.6.24-24-generic)JDK:1.6第一回合: Java测试先说明一下,Java并不支持System V消息队列,因此特为Java提供了JNI接口,我们使用lajp_9.09提供C源码编译的so动态连接库,lajp的下载地址和文档:/p/lajp/首先上场的是System V消息队列。发送端程序:package test;import lajp.MsgQ;public class TestSend /* 消息队列KEY */ static final int IPC_KEY = 020021230; static /JNI System.loadLibrary(lajpmsgq); public static void main(String args) /创建或获得现有的消息队列 int msqid = MsgQ.msgget(IPC_KEY); /发送字节数组 byte msg = new byte1024; for (int i = 0; i 1024 * 5000; i+) /每次发送1204字节到消息队列,9527是消息类型 MsgQ.msgsnd(msqid, 9527, msg, msg.length); System.out.println(发送结束.); 接收端程序:package test;import lajp.MsgQ;public class TestRcv /* 消息队列KEY */ static final int IPC_KEY = 020021230; static /JNI System.loadLibrary(lajpmsgq); public static void main(String args) /创建或获得现有的消息队列 int msqid = MsgQ.msgget(IPC_KEY); /接收缓冲区 byte msg = new byte1024; long start = System.currentTimeMillis(); /开始时间 for (int i = 0; i 1024 * 5000; i+) /每次从消息队列中接收消息类型为9527的消息,接收1204字节 MsgQ.msgrcv(msqid, msg, msg.length, 9527); long end = System.currentTimeMillis(); /结束时间 System.out.println(用时: + (end start) + 毫秒); 程序很简单,需要说明的是三个JNI方法调用:msgget()方法: System V消息队列的技术要求,含义是通过一个指定的KEY获得消息队列标识符。msgsnd()方法: 发送。msgrcv()方法: 接收。发送方进行了(1024 * 5000)次发送,每次发送1024字节数据,接收方进行了(1024 * 5000)次接收,每次接收1024字节,共计发送接收5G数据。测试时先启动TestSend程序,再启动TestRcv程序,共进行5轮次测试,测试结果如下:用时:29846毫秒用时:29591毫秒用时:29935毫秒用时:29730毫秒用时:29468毫秒平均速度:29714毫秒用top命令监控测试期间的CPU、内存的使用:接下来上场的是socket。发送端程序:import java.io.IOException;import java.io.OutputStream;import .Socket; public class SocketSend public static void main(String args) throws IOException /Socket Socket socket = new Socket(, 9527); /输出流 OutputStream out = socket.getOutputStream(); /发送字节数组 byte msg = new byte1024; long start = System.currentTimeMillis(); /开始时间 for (int i = 0; i 1024 * 5000; i+) /发送 out.write(msg); long end = System.currentTimeMillis(); /结束时间 System.out.println(用时: + (end start) + 毫秒); 接收端程序:import java.io.IOException;import java.io.InputStream;import .ServerSocket;import .Socket;public class SocketRecv public static void main(String args) throws IOException /侦听9527端口 ServerSocket serverSocket = new ServerSocket(9527); /Socket Socket socket = serverSocket.accept(); /输入流 InputStream in = socket.getInputStream(); /接收缓冲区 byte msg = new byte1024; for (int i = 0; i 1024 * 5000; i+) /每次接收1204字节 in.read(msg); System.out.println(接受结束.); 程序同样很简单,同样发送接收了(1024 * 5000)次,同样5G数据,socket程序必须先启动服务方SocketRecv,然后启动客户方SocketSend,共进行5轮次测试,测试结果如下:用时:33951毫秒用时:33448毫秒用时:33987毫秒用时:34638毫秒用时:33957毫秒平均速度:33996.2毫秒用top命令监控测试期间的CPU、内存的使用:测试结果让人对消息队列有点失望,性能优势微弱大约只领先了13%,且程序复杂性要大的多(使用了JNI)。不过重新审视测试过程有一个疑问:消息队列程序调用了自定义的JNI接口,而socket是Java内嵌的功能,是否JVM对 socket有特殊的优化呢?怀着这个疑问,进行第二场纯C程序的测试。第二回合: C程序测试首先上场的还是System V消息队列。发送端程序:#include #include #include #define IPC_KEY 020021230 /* 消息队列KEY */ /*消息结构*/ struct message long msg_type; /* 消息标识符 */ char msg_text1024; /* 消息内容 */; int main() /* 创建或获得现有的消息队列 */ int msqid = msgget(IPC_KEY, IPC_CREAT | 0666); /* 消息结构 */ struct message msgq; msgq.msg_type = 9527; /* 消息类型 */ int i; for (i = 0; i 1024 * 5000; i+) /* 接收 */ msgsnd(msqid, &msgq, 1024, 0); printf(msgq发送结束,共发送%d次n, i); return 0;接收端程序: #include #include #include #define IPC_KEY 020021230 /* 消息队列KEY */ /*消息结构*/ struct message long msg_type; /* 消息标识符 */ char msg_text1024; /* 消息内容 */; int main() /* 创建或获得现有的消息队列 */ int msqid = msgget(IPC_KEY, IPC_CREAT | 0666); /* 消息结构 */ struct message msgq; int i; for (i = 0; i 1024 * 5000; i+) /* 接收 */ msgrcv(msqid, &msgq, 1024, 9527, 0); printf(msgq接收结束,共接收%d次n, i); return 0;和第一场一样,发送接收了(1024 * 5000)次,同样5G数据,先启动接收端程序msgrecv,然后以$time msgsend方式启动客户端程序,共进行5轮次测试,time的测试结果如下:用户 系统 时钟第一次: 0.992s 7.084s 18.202s第二次: 0.888s 7.280s 18.815s第三次: 1.060s 7.656s 19.476s第四次: 1.048s 7.124s 20.293s第五次: 1.008s 7.160s 18.655s用top命令监控测试期间的CPU、内存的使用:接下来上场的是socket。发送端程序:#include #include #include char msg1024; /* 发送消息 */ int main() char *ip = ; /* 发送地址 */ int port = 9527; /* 发送端口 */ struct hostent *server_host = gethostbyname(ip); /* 客户端填充 sockaddr 结构 */ struct sockaddr_in client_addr; /* 客户端地址结构 */ bzero(&client_addr, sizeof(client_addr); client_addr.sin_family = AF_INET; /* AF_INET:IPV4协议 */ client_addr.sin_addr.s_addr = (struct in_addr *)(server_host-h_addr)-s_addr; /* 服务端地址 */ client_addr.sin_port = htons(port); /* 端口 */ /* 建立socket */ int sockfd = socket(AF_INET, SOCK_STREAM, 0); /* 连接 */ connect(sockfd, (struct sockaddr *)(&client_addr), sizeof(client_addr); int i; for (i = 0; i 1024 * 5000; i+) /* 发送 */ send(sockfd, msg, 1024, 0); printf(发送结束,共发送%d次n, i); return 0;接收端程序: #include #include #include char msg1024; /* 接收缓冲区 */ int main() int listen_port = 9527; /* 侦听端口 */ int listenfd = socket(AF_INET, SOCK_STREAM, 0); /* 建立侦听socket */ /* 服务端填充 sockaddr 结构 */ struct sockaddr_in server_addr; /* 服务端地址结构 */ bzero(&server_addr, sizeof(server_addr); server_addr.sin_family = AF_INET; /* AF_INET:IPV4协议 */ server_addr.sin_addr.s_addr = htonl(INADDR_ANY); /* INADDR_ANY:通配地址,表示内核选择IP地址 */ server_addr.sin_port = htons(listen_port); /* 端口 */ /* 绑定端口 */ bind(listenfd, (struct sockaddr *)(&server_addr), sizeof(server_addr); /* 侦听 */ listen(listenfd, 5); int sockfd = accept(listenfd, NULL, NULL); int i; for (i = 0; i 1024 * 5000; i+) /* 接收 */ recv(sockfd, msg, 1024, 0); printf(接收结束,共接收%d次n, i); return 0;C语言中,socket程序复杂了不少。测试标准和Java相同,发送接收了(1024 * 5000)次,5G数据,先启动接收端程序,然后以time方式启动发送端,测试结果如下:用户 系统 时钟第一次: 0.524s 9.765s 20.666s第二次: 0.492s 9.825s 20.530s第三次: 0.468s 9.493s 21.831s第四次: 0.512s 9.205s 20.059s第五次: 0.440s 9.605s 21.888s用top命令监控测试期间的CPU、内存的使用:C语言的socket程序系统用时多一些,消息队列程序用户用时多一些,这和他们的实现方式相关,从时钟比较看,消息队列比socket快10%左右,和Java测试结果相似。比较Java和C,C只领先了三分之一,看来当前的Java效率已经相当高了。还不能忙于下结论,socket的通信方式一般有两种:长连接和短连接。长连接指发送端和接收端建立连接后,可以保持socket通道进行多次消息传输,在这种场景基本不用计算socket建立和关闭的时间,前面的测试都是基于长连接方式;短连接一般在建立socket通道后,只进行一次通信,然后就关闭 socket通道,这种场景必须考虑socket建立和关闭的时间(socket建立连接需要三次握手,关闭连接要四次通信)。第三回合: Java测试(短连接)将第一回合中的Java程序稍作修改,先看socket的:发送端程序:import java.io.IOException;import java.io.OutputStream;import .Socket;public class SocketSend2 public static void main(String args) throws IOException long start = System.currentTimeMillis(); /开始时间 /发送字节数组 byte msg = new byte1024; for (int i = 0; i 1024 * 1000; i+) /建立Socket连接 Socket socket = new Socket(, 9527); /输出流 OutputStream out = socket.getOutputStream(); /发送 out.write(msg); /关闭输出流 out.close(); /关闭socket连接 socket.close(); long end = System.currentTimeMillis(); /结束时间 System.out.println(用时: + (end start) + 毫秒); 建立socket的语句放在了循环内部,这样每次发送都是新建的连接,025行的关闭语句是必须的,因为socket是系统的有限资源,支持不了这么大规模的申请。接收端程序:import java.io.IOException;import java.io.InputStream;import .ServerSocket;import .Socket;public class SocketRecv2 public static void main(String args) throws IOException /侦听9527端口 ServerSocket serverSocket = new ServerSocket(9527); /接收缓冲区 byte msg = new byte1024; for (int i = 0; i 1024 * 1000; i+) /接到客户端Socket连接请求 Socket socket = serverSocket.accept(); /输入流 InputStream in = socket.getInputStream(); /每次接收1204字节 in.read(msg); /关闭输入流 in.close(); /关闭socket连接 socket.close(); System.out.println(接受结束.); 接收端也做了相应的改动,发送和接收次数降低到(1024 * 1000)次,测试结果:431280毫秒,不要吃惊,没错是431.280秒,这也是书本上为什么总在强调使用数据库连接池的原因。消息队列没有像socket那样的连接概念,为了做个参考,将第一回合中的消息队列程序也修改一下:发送端程序:package test;import lajp.MsgQ;public class TestSend2 /* 消息队列KEY */ static final int IPC_KEY = 020021230; static /JNI System.loadLibrary(lajpmsgq); public static void main(String args) /发送
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 2025年海南省通信网络技术保障中心招聘考试笔试试题(含答案)
- 2025年国家卫生健康委医药卫生科技发展研究中心招聘考试笔试试题(含答案)
- 2025年桂林市机电职业技术学校教师岗位招聘考试笔试试题(含答案)
- 咖啡民宿结合创新创业项目商业计划书
- 移动广告联盟与收益分成模式创新创业项目商业计划书
- 农品易购站创新创业项目商业计划书
- 农产品豆腐制品创新创业项目商业计划书
- 2025年甘肃省酒泉老年大学招聘教师试题(含答案)
- 社交电商用户忠诚度提升创新创业项目商业计划书
- 汽车自动化库存管理创新创业项目商业计划书
- 2025年锅炉检验员资格考试试卷:锅炉检验员考试模拟试题与解析
- 淋巴瘤健康教育课件
- 煤灰管道清理方案(3篇)
- 2025年河北大学版(2024)小学信息科技三年级(全一册)教学设计(附目录 P179)
- 安保技能活动方案
- 物资部档案管理制度
- 2025-2030中国烟花爆竹市场竞争动态分析及前景销售格局研究报告
- 2025年普通高等学校招生全国统一考试数学试题(全国一卷)(有解析)
- 比亚迪公司薪酬管理制度
- 公司监控视频管理制度
- 交通事故护工合同范本
评论
0/150
提交评论