正在显示
1 个修改的文件
包含
268 行增加
和
0 行删除
src/server/spserver/teststress.cpp
0 → 100644
1 | +/* | ||
2 | + * Copyright 2007 Stephen Liu | ||
3 | + * For license terms, see the file COPYING along with this library. | ||
4 | + */ | ||
5 | + | ||
6 | +#include <signal.h> | ||
7 | +#include <stdio.h> | ||
8 | +#include <sys/types.h> | ||
9 | +#include <stdlib.h> | ||
10 | +#include <errno.h> | ||
11 | +#include <time.h> | ||
12 | +#include <string.h> | ||
13 | + | ||
14 | +#ifdef WIN32 | ||
15 | +#include "spgetopt.h" | ||
16 | +#endif | ||
17 | + | ||
18 | +#include "spporting.hpp" | ||
19 | + | ||
20 | +#include "event.h" | ||
21 | + | ||
22 | +static const char * gHost = "127.0.0.1"; | ||
23 | +static int gPort = 3333; | ||
24 | +static int gMsgs = 10; | ||
25 | +static int gClients = 10; | ||
26 | +static int gConnWait = 0; | ||
27 | +static int gSockWait = 0; | ||
28 | + | ||
29 | +static time_t gStartTime = 0; | ||
30 | + | ||
31 | +struct SP_TestClient { | ||
32 | + int mFd; | ||
33 | + struct event mReadEvent; | ||
34 | + struct event mWriteEvent; | ||
35 | + int mSendMsgs; | ||
36 | + int mRecvMsgs; | ||
37 | + char mBuffer[ 512 ]; | ||
38 | +}; | ||
39 | + | ||
40 | +void showUsage( const char * program ) | ||
41 | +{ | ||
42 | + printf( "\nStress Test Tools for spserver example -- testecho/testchat\n\n" ); | ||
43 | + printf( "Usage: %s [-h <host>] [-p <port>] [-c <clients>] [-m <messages>]\n" | ||
44 | + "\t\t\t[-w <connect wait>] [-s <socket wait>]\n\n", program ); | ||
45 | + printf( "\t-h default is %s\n", gHost ); | ||
46 | + printf( "\t-p default is %d\n", gPort ); | ||
47 | + printf( "\t-c how many clients, default is %d\n", gClients ); | ||
48 | + printf( "\t-m messages per client, default is %d\n", gMsgs ); | ||
49 | + printf( "\t-w how many milliseconds to wait between creating every 100 connections, default is %d\n", gConnWait ); | ||
50 | + printf( "\t-s how many milliseconds to wait between every event loop, default is %d\n", gSockWait ); | ||
51 | + printf( "\n" ); | ||
52 | +} | ||
53 | + | ||
54 | +void close_read( SP_TestClient * client ) | ||
55 | +{ | ||
56 | + //fprintf( stderr, "#%d close read\n", client->mFd ); | ||
57 | + event_del( &client->mReadEvent ); | ||
58 | + gClients--; | ||
59 | +} | ||
60 | + | ||
61 | +void close_write( SP_TestClient * client ) | ||
62 | +{ | ||
63 | + //fprintf( stderr, "#%d close write\n", client->mFd ); | ||
64 | + event_del( &client->mWriteEvent ); | ||
65 | +} | ||
66 | + | ||
67 | +void close_client( SP_TestClient * client ) | ||
68 | +{ | ||
69 | + close_write( client ); | ||
70 | + close_read( client ); | ||
71 | +} | ||
72 | + | ||
73 | +void on_read( int fd, short events, void *arg ) | ||
74 | +{ | ||
75 | + SP_TestClient * client = ( SP_TestClient * ) arg; | ||
76 | + | ||
77 | + if( EV_READ & events ) { | ||
78 | + int len = recv( fd, client->mBuffer, sizeof( client->mBuffer ), 0 ); | ||
79 | + if( len <= 0 ) { | ||
80 | + if( len < 0 && EAGAIN != errno ) { | ||
81 | + fprintf( stderr, "#%d on_read error, count %d, errno %d, %s\n", | ||
82 | + fd, client->mRecvMsgs, errno, strerror( errno ) ); | ||
83 | + } | ||
84 | + close_client( client ); | ||
85 | + } else { | ||
86 | + for( int i = 0; i < len; i++ ) { | ||
87 | + //if( 10 == fd ) printf( "%c", client->mBuffer[i] ); | ||
88 | + if( '\n' == client->mBuffer[i] ) client->mRecvMsgs++; | ||
89 | + } | ||
90 | + } | ||
91 | + } else { | ||
92 | + fprintf( stderr, "#%d on_read timeout\n", fd ); | ||
93 | + close_client( client ); | ||
94 | + } | ||
95 | +} | ||
96 | + | ||
97 | +void on_write( int fd, short events, void *arg ) | ||
98 | +{ | ||
99 | + SP_TestClient * client = ( SP_TestClient * ) arg; | ||
100 | + | ||
101 | + if( EV_WRITE & events ) { | ||
102 | + client->mSendMsgs++; | ||
103 | + | ||
104 | + if( client->mSendMsgs >= gMsgs ) { | ||
105 | + snprintf( client->mBuffer, sizeof( client->mBuffer ), "quit\n" ); | ||
106 | + } else { | ||
107 | + snprintf( client->mBuffer, sizeof( client->mBuffer ), | ||
108 | + "mail #%d, It's good to see how people hire; " | ||
109 | + "that tells us how to market ourselves to them.\n", client->mSendMsgs ); | ||
110 | + } | ||
111 | + | ||
112 | + int len = send( fd, client->mBuffer, strlen( client->mBuffer ), 0 ); | ||
113 | + | ||
114 | + if( len <= 0 && EAGAIN != errno ) { | ||
115 | + fprintf( stderr, "#%d on_write error, errno %d, %s\n", fd, errno, strerror( errno ) ); | ||
116 | + close_client( client ); | ||
117 | + } else { | ||
118 | + if( client->mSendMsgs >= gMsgs ) close_write( client ); | ||
119 | + } | ||
120 | + } else { | ||
121 | + fprintf( stderr, "#%d on_write timeout\n", fd ); | ||
122 | + close_client( client ); | ||
123 | + } | ||
124 | +} | ||
125 | + | ||
126 | +void parse_arg( int argc, char * argv[] ) | ||
127 | +{ | ||
128 | + extern char *optarg ; | ||
129 | + int c ; | ||
130 | + | ||
131 | + while( ( c = getopt ( argc, argv, "h:p:c:m:w:s:v" )) != EOF ) { | ||
132 | + switch ( c ) { | ||
133 | + case 'h' : | ||
134 | + gHost = optarg; | ||
135 | + break; | ||
136 | + case 'p': | ||
137 | + gPort = atoi( optarg ); | ||
138 | + break; | ||
139 | + case 'c' : | ||
140 | + gClients = atoi ( optarg ); | ||
141 | + break; | ||
142 | + case 'm' : | ||
143 | + gMsgs = atoi( optarg ); | ||
144 | + break; | ||
145 | + case 'w': | ||
146 | + gConnWait = atoi( optarg ); | ||
147 | + break; | ||
148 | + case 's': | ||
149 | + gSockWait = atoi( optarg ); | ||
150 | + break; | ||
151 | + case 'v' : | ||
152 | + case '?' : | ||
153 | + showUsage( argv[0] ); | ||
154 | + exit( 0 ); | ||
155 | + } | ||
156 | + } | ||
157 | +} | ||
158 | + | ||
159 | +int main( int argc, char * argv[] ) | ||
160 | +{ | ||
161 | + parse_arg( argc, argv ); | ||
162 | + | ||
163 | +#ifdef SIGPIPE | ||
164 | + signal( SIGPIPE, SIG_IGN ); | ||
165 | +#endif | ||
166 | + | ||
167 | + sp_initsock(); | ||
168 | + | ||
169 | + event_init(); | ||
170 | + | ||
171 | + SP_TestClient * clientList = (SP_TestClient*)calloc( gClients, sizeof( SP_TestClient ) ); | ||
172 | + | ||
173 | + struct sockaddr_in sin; | ||
174 | + memset( &sin, 0, sizeof(sin) ); | ||
175 | + sin.sin_family = AF_INET; | ||
176 | + sin.sin_addr.s_addr = inet_addr( gHost ); | ||
177 | + sin.sin_port = htons( gPort ); | ||
178 | + | ||
179 | + int totalClients = gClients, i = 0; | ||
180 | + | ||
181 | + printf( "Create %d connections to server, it will take some minutes to complete.\n", gClients ); | ||
182 | + for( i = 0; i < gClients; i++ ) { | ||
183 | + SP_TestClient * client = clientList + i; | ||
184 | + | ||
185 | + client->mFd = socket( AF_INET, SOCK_STREAM, 0 ); | ||
186 | + if( client->mFd < 0 ) { | ||
187 | + fprintf(stderr, "#%d, socket failed, errno %d, %s\n", i, errno, strerror( errno ) ); | ||
188 | +#ifdef WIN32 | ||
189 | + spwin32_pause_console(); | ||
190 | +#endif | ||
191 | + return -1; | ||
192 | + } | ||
193 | + | ||
194 | + if( connect( client->mFd, (struct sockaddr *)&sin, sizeof(sin) ) != 0) { | ||
195 | + fprintf(stderr, "#%d, connect failed, errno %d, %s\n", i, errno, strerror( errno ) ); | ||
196 | +#ifdef WIN32 | ||
197 | + spwin32_pause_console(); | ||
198 | +#endif | ||
199 | + return -1; | ||
200 | + } | ||
201 | + | ||
202 | + event_set( &client->mWriteEvent, client->mFd, EV_WRITE | EV_PERSIST, on_write, client ); | ||
203 | + event_add( &client->mWriteEvent, NULL ); | ||
204 | + | ||
205 | + event_set( &client->mReadEvent, client->mFd, EV_READ | EV_PERSIST, on_read, client ); | ||
206 | + event_add( &client->mReadEvent, NULL ); | ||
207 | + | ||
208 | + if( 0 == ( i % 10 ) ) write( fileno( stdout ), ".", 1 ); | ||
209 | + | ||
210 | + if( gConnWait > 0 && ( i > 0 ) && ( 0 == ( i % 100 ) ) ) usleep( gConnWait * 1000 ); | ||
211 | + } | ||
212 | + | ||
213 | + time( &gStartTime ); | ||
214 | + | ||
215 | + struct timeval startTime, stopTime; | ||
216 | + | ||
217 | + sp_gettimeofday( &startTime, NULL ); | ||
218 | + | ||
219 | + time_t lastInfoTime = time( NULL ); | ||
220 | + | ||
221 | + // start event loop until all clients are exit | ||
222 | + while( gClients > 0 ) { | ||
223 | + event_loop( EVLOOP_ONCE ); | ||
224 | + | ||
225 | + if( time( NULL ) - lastInfoTime > 5 ) { | ||
226 | + time( &lastInfoTime ); | ||
227 | + printf( "waiting for %d client(s) to exit\n", gClients ); | ||
228 | + } | ||
229 | + | ||
230 | + if( gSockWait > 0 ) usleep( gSockWait * 1000 ); | ||
231 | + } | ||
232 | + | ||
233 | + sp_gettimeofday( &stopTime, NULL ); | ||
234 | + | ||
235 | + double totalTime = (double) ( 1000000 * ( stopTime.tv_sec - startTime.tv_sec ) | ||
236 | + + ( stopTime.tv_usec - startTime.tv_usec ) ) / 1000000; | ||
237 | + | ||
238 | + // show result | ||
239 | + printf( "\n\nTest result :\n" ); | ||
240 | + printf( "Host %s, Port %d, ConnWait: %d, SockWait: %d\n", gHost, gPort, gConnWait, gSockWait ); | ||
241 | + printf( "Clients : %d, Messages Per Client : %d\n", totalClients, gMsgs ); | ||
242 | + printf( "ExecTimes: %.6f seconds\n\n", totalTime ); | ||
243 | + | ||
244 | + printf( "client\tSend\tRecv\n" ); | ||
245 | + int totalSend = 0, totalRecv = 0; | ||
246 | + for( i = 0; i < totalClients; i++ ) { | ||
247 | + SP_TestClient * client = clientList + i; | ||
248 | + | ||
249 | + //printf( "client#%d : %d\t%d\n", i, client->mSendMsgs, client->mRecvMsgs ); | ||
250 | + | ||
251 | + totalSend += client->mSendMsgs; | ||
252 | + totalRecv += client->mRecvMsgs; | ||
253 | + | ||
254 | + sp_close( client->mFd ); | ||
255 | + } | ||
256 | + | ||
257 | + printf( "total : %d\t%d\n", totalSend, totalRecv ); | ||
258 | + printf( "average : %.0f/s\t%.0f/s\n", totalSend / totalTime, totalRecv / totalTime ); | ||
259 | + | ||
260 | + free( clientList ); | ||
261 | + | ||
262 | +#ifdef WIN32 | ||
263 | + spwin32_pause_console(); | ||
264 | +#endif | ||
265 | + | ||
266 | + return 0; | ||
267 | +} | ||
268 | + |
请
注册
或
登录
后发表评论