Unix域上的套接字在Solaris 10上比在Linux上慢100倍?
发布时间:2020-12-15 22:57:23 所属栏目:安全 来源:网络整理
导读:我正在为 Linux项目和 Linux上的本地套接字性能进行基准测试.出于某种原因,我无法发现,Solaris上的性能比Linux上差100倍.在Linux中,打开一个套接字,每次交换一个非常短(2个字符)的消息并关闭它需要大约10us的时间.在Solaris上,同样的事情需要大约1000us. 设
我正在为
Linux项目和
Linux上的本地套接字性能进行基准测试.出于某种原因,我无法发现,Solaris上的性能比Linux上差100倍.在Linux中,打开一个套接字,每次交换一个非常短(2个字符)的消息并关闭它需要大约10us的时间.在Solaris上,同样的事情需要大约1000us.
设置是Virtual Box和Linux中的Solaris 10开发人员vm,它们位于同一个虚拟盒中,并且直接位于相同的硬件上(没有区别). 这是Solaris的已知问题吗?有办法解决吗?我无法使用本地网络连接,原因是我无法进入此处. 下面的客户端和服务器代码.使用“cc -fast -m64 -lrt -lsocket -lnsl -o server server.c”和客户端的等效文件进行编译.随Solaris 10提供的Gcc 3.4.3给出了可比较的结果.此代码已被删除,例如已删除超时结束错误处理是最小的. server.c: #include <stdio.h> #include <stdlib.h> #include <errno.h> #include <ctype.h> #include <sys/select.h> #include <sys/socket.h> #include <sys/stat.h> #include <sys/types.h> #include <sys/un.h> #include <time.h> #include <string.h> #include <unistd.h> #define DIRECTORY "sub/" #define FULL_PATH "sub/c_socket" #define MAX_COMMAND_LEN 8192 #define PERMISSIONS 0700 void on_error(int err,char * msg) { // simple convenient error handler if (err == -1) { // Tests whether 'err' is -1 and perror(msg); // prints error and msg if so. exit(-1); } } int main() { struct sockaddr_un addr; int srv_fd,inst_fd; int inst_adr_size; char c; int ret; char readbuf[MAX_COMMAND_LEN]; int num_read; fd_set rfds; int fail; int i; // make address memset(&addr,sizeof(addr)); // clear out addr addr.sun_family = AF_UNIX; strncpy(addr.sun_path,FULL_PATH,sizeof(addr.sun_path)); // Remove old pseudo file if present ret = unlink(FULL_PATH); if (ret == -1 && errno != ENOENT) { on_error(ret,"nRemoving old socket filen"); } // Remove old directory if present ret = rmdir(DIRECTORY); if (ret == -1 && errno != ENOENT) { on_error(ret,"nRemoving old socket directoryn"); } // Re-create new directory with appropriate permissonsm ret = mkdir(DIRECTORY,PERMISSIONS); on_error(ret,"nCreating directoroy for socket filen"); // create server listening socket srv_fd = socket(AF_UNIX,SOCK_STREAM,0); on_error(srv_fd,"nSocket creation:n"); // bind server listening socket to address ret = bind(srv_fd,(struct sockaddr *) &addr,sizeof(addr)); on_error(ret,"nSocket binding:n"); // set file permissions for socket file (somewhat redundant) ret = chmod(FULL_PATH,"nSetting socket file permissionsn"); // set socket listening and queue length ret = listen(srv_fd,10); on_error(ret,"nSet socket to listen:n"); while(1) { // accept requests inst_fd = accept(srv_fd,NULL,NULL); on_error(inst_fd,"n accepting connection:n"); // prepare to use select on inst_fd FD_ZERO(&rfds); FD_SET(inst_fd,&rfds); // now interact with the client on the instance socket. while(1) { num_read = 0; while (1) { // read a line terminated by 'n' ret = select(inst_fd + 1,&rfds,NULL); on_error(ret,"nSelect on socketn"); if (ret == 1) { // we can read something ret = recv(inst_fd,readbuf+num_read,MAX_COMMAND_LEN-num_read,0 on_error(ret,"nrecv:n"); if (ret == 0) { break; // we have EOF } num_read += ret; if (readbuf[num_read - 1] == 'n') { break; } } } /* reading one input line done */ if (num_read == 0) break; // EOF propagated // process command: Just send 2 chars back ret = send(inst_fd,"nn",2,0); } close(inst_fd); // clean up } // runs forever... } client.c: #include <stdio.h> #include <time.h> #include <sys/socket.h> #include <sys/un.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #define RCVBUFSIZE 8192 /* Size of receive buffer */ #define FULL_PATH "sub/c_socket" #define CYCLES 100000 void on_error(int err,char * msg) { // more convenient error output if (err == -1) { // Tests whether 'err' is -1 and perror(msg); // prints error and msg if so. exit(-1); } } int main(int argc,char *argv[]) { int client_fd; struct sockaddr_un addr; char readbuf[RCVBUFSIZE+1]; int num_read; int ret; int count; fd_set rfds; char * msg = "Nn"; // make address memset(&addr,sizeof(addr.sun_path)); for(count = 0; count < CYCLES; count++) { // create socket client_fd = socket(PF_UNIX,0); on_error(client_fd,"socket() failed"); // prepare to use select on inst_fd FD_ZERO(&rfds); FD_SET(client_fd,&rfds); // connect ret = connect(client_fd,sizeof(addr)); on_error(ret,"connect() failed"); // send msg to server ret = send(client_fd,msg,0); if (ret != 2) { on_error(-1,"nnot all bytes sentn"); } num_read = 0; // read until we have a 'n' while (1) { ret = select(client_fd + 1,NULL); on_error(ret,"nSelect on socketn"); if (ret == 1) { // we can read something ret = recv(client_fd,readbuf + num_read,RCVBUFSIZE - num_read,0) on_error(ret,"nrecv:n"); num_read += ret; if (readbuf[num_read - 1] == 'n') break; } } if (num_read == 0) break; close(client_fd); } return(0); } 解决方法
当我研究套接字并尝试编写ftp服务器时,我遇到了类似的问题:由于转换为ascii中的一个错误,我最终一次只写一个字节的文件,但是在linux上它没关系,而在Windows上我最终在循环接口上使用类似100KB / s的东西……如果是这种情况,增加字节数应该可以减少很多差异.
似乎在Linux下,请求系统调用的行为更快. PS (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |