📄 thruput.c
字号:
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- *//* * The contents of this file are subject to the Mozilla Public * License Version 1.1 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of * the License at http://www.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or * implied. See the License for the specific language governing * rights and limitations under the License. * * The Original Code is the Netscape Portable Runtime (NSPR). * * The Initial Developer of the Original Code is Netscape * Communications Corporation. Portions created by Netscape are * Copyright (C) 1998-2000 Netscape Communications Corporation. All * Rights Reserved. * * Contributor(s): * * Alternatively, the contents of this file may be used under the * terms of the GNU General Public License Version 2 or later (the * "GPL"), in which case the provisions of the GPL are applicable * instead of those above. If you wish to allow use of your * version of this file only under the terms of the GPL and not to * allow others to use your version of this file under the MPL, * indicate your decision by deleting the provisions above and * replace them with the notice and other provisions required by * the GPL. If you do not delete the provisions above, a recipient * may use your version of this file under either the MPL or the * GPL. *//*** File: thruput.c** Description: Test server's throughput capability comparing various** implmentation strategies.**** Note: Requires a server machine and an aribitrary number of** clients to bang on it. Trust the numbers on the server** more than those being displayed by the various clients.*/#include "prerror.h"#include "prinrval.h"#include "prinit.h"#include "prio.h"#include "prlock.h"#include "prmem.h"#include "prnetdb.h"#include "prprf.h"#include "prthread.h"#include "pprio.h"#include "plerror.h"#include "plgetopt.h"#define ADDR_BUFFER 100#define PORT_NUMBER 51877#define SAMPLING_INTERVAL 10#define BUFFER_SIZE (32 * 1024)static PRInt32 domain = PR_AF_INET;static PRInt32 protocol = 6; /* TCP */static PRFileDesc *err = NULL;static PRIntn concurrency = 1;static PRInt32 xport_buffer = -1;static PRUint32 initial_streams = 1;static PRInt32 buffer_size = BUFFER_SIZE;static PRThreadScope thread_scope = PR_LOCAL_THREAD;typedef struct Shared{ PRLock *ml; PRUint32 sampled; PRUint32 threads; PRIntervalTime timein; PRNetAddr server_address;} Shared;static Shared *shared = NULL;static PRStatus PrintAddress(const PRNetAddr* address){ char buffer[ADDR_BUFFER]; PRStatus rv = PR_NetAddrToString(address, buffer, sizeof(buffer)); if (PR_SUCCESS == rv) PR_fprintf(err, "%s:%u\n", buffer, PR_ntohs(address->inet.port)); else PL_FPrintError(err, "PR_NetAddrToString"); return rv;} /* PrintAddress */static void PR_CALLBACK Clientel(void *arg){ PRStatus rv; PRFileDesc *xport; PRInt32 bytes, sampled; PRIntervalTime now, interval; PRBool do_display = PR_FALSE; Shared *shared = (Shared*)arg; char *buffer = (char*)PR_Malloc(buffer_size); PRNetAddr *server_address = &shared->server_address; PRIntervalTime connect_timeout = PR_SecondsToInterval(5); PRIntervalTime sampling_interval = PR_SecondsToInterval(SAMPLING_INTERVAL); PR_fprintf(err, "Client connecting to "); (void)PrintAddress(server_address); do { xport = PR_Socket(domain, PR_SOCK_STREAM, protocol); if (NULL == xport) { PL_FPrintError(err, "PR_Socket"); return; } if (xport_buffer != -1) { PRSocketOptionData data; data.option = PR_SockOpt_RecvBufferSize; data.value.recv_buffer_size = (PRSize)xport_buffer; rv = PR_SetSocketOption(xport, &data); if (PR_FAILURE == rv) PL_FPrintError(err, "PR_SetSocketOption - ignored"); data.option = PR_SockOpt_SendBufferSize; data.value.send_buffer_size = (PRSize)xport_buffer; rv = PR_SetSocketOption(xport, &data); if (PR_FAILURE == rv) PL_FPrintError(err, "PR_SetSocketOption - ignored"); } rv = PR_Connect(xport, server_address, connect_timeout); if (PR_FAILURE == rv) { PL_FPrintError(err, "PR_Connect"); if (PR_IO_TIMEOUT_ERROR != PR_GetError()) PR_Sleep(connect_timeout); PR_Close(xport); /* delete it and start over */ } } while (PR_FAILURE == rv); do { bytes = PR_Recv( xport, buffer, buffer_size, 0, PR_INTERVAL_NO_TIMEOUT); PR_Lock(shared->ml); now = PR_IntervalNow(); shared->sampled += bytes; interval = now - shared->timein; if (interval > sampling_interval) { sampled = shared->sampled; shared->timein = now; shared->sampled = 0; do_display = PR_TRUE; } PR_Unlock(shared->ml); if (do_display) { PRUint32 rate = sampled / PR_IntervalToMilliseconds(interval); PR_fprintf(err, "%u streams @ %u Kbytes/sec\n", shared->threads, rate); do_display = PR_FALSE; } } while (bytes > 0);} /* Clientel */static void Client(const char *server_name){ PRStatus rv; PRHostEnt host; char buffer[PR_NETDB_BUF_SIZE]; PRIntervalTime dally = PR_SecondsToInterval(60); PR_fprintf(err, "Translating the name %s\n", server_name); rv = PR_GetHostByName(server_name, buffer, sizeof(buffer), &host); if (PR_FAILURE == rv) PL_FPrintError(err, "PR_GetHostByName"); else { if (PR_EnumerateHostEnt( 0, &host, PORT_NUMBER, &shared->server_address) < 0) PL_FPrintError(err, "PR_EnumerateHostEnt"); else { do { shared->threads += 1; (void)PR_CreateThread( PR_USER_THREAD, Clientel, shared, PR_PRIORITY_NORMAL, thread_scope, PR_UNJOINABLE_THREAD, 8 * 1024); if (shared->threads == initial_streams) { PR_Sleep(dally); initial_streams += 1; } } while (PR_TRUE); } }}static void PR_CALLBACK Servette(void *arg){ PRInt32 bytes, sampled; PRIntervalTime now, interval; PRBool do_display = PR_FALSE; PRFileDesc *client = (PRFileDesc*)arg; char *buffer = (char*)PR_Malloc(buffer_size); PRIntervalTime sampling_interval = PR_SecondsToInterval(SAMPLING_INTERVAL); if (xport_buffer != -1) { PRStatus rv; PRSocketOptionData data; data.option = PR_SockOpt_RecvBufferSize; data.value.recv_buffer_size = (PRSize)xport_buffer; rv = PR_SetSocketOption(client, &data); if (PR_FAILURE == rv) PL_FPrintError(err, "PR_SetSocketOption - ignored"); data.option = PR_SockOpt_SendBufferSize; data.value.send_buffer_size = (PRSize)xport_buffer; rv = PR_SetSocketOption(client, &data); if (PR_FAILURE == rv) PL_FPrintError(err, "PR_SetSocketOption - ignored"); } do { bytes = PR_Send( client, buffer, buffer_size, 0, PR_INTERVAL_NO_TIMEOUT); PR_Lock(shared->ml); now = PR_IntervalNow(); shared->sampled += bytes; interval = now - shared->timein; if (interval > sampling_interval) { sampled = shared->sampled; shared->timein = now; shared->sampled = 0; do_display = PR_TRUE; } PR_Unlock(shared->ml); if (do_display) { PRUint32 rate = sampled / PR_IntervalToMilliseconds(interval); PR_fprintf(err, "%u streams @ %u Kbytes/sec\n", shared->threads, rate); do_display = PR_FALSE; } } while (bytes > 0);} /* Servette */static void Server(void){ PRStatus rv; PRNetAddr server_address, client_address; PRFileDesc *xport = PR_Socket(domain, PR_SOCK_STREAM, protocol); if (NULL == xport) { PL_FPrintError(err, "PR_Socket"); return; } rv = PR_InitializeNetAddr(PR_IpAddrAny, PORT_NUMBER, &server_address); if (PR_FAILURE == rv) PL_FPrintError(err, "PR_InitializeNetAddr"); else { rv = PR_Bind(xport, &server_address); if (PR_FAILURE == rv) PL_FPrintError(err, "PR_Bind"); else { PRFileDesc *client; rv = PR_Listen(xport, 10); PR_fprintf(err, "Server listening on "); (void)PrintAddress(&server_address); do { client = PR_Accept( xport, &client_address, PR_INTERVAL_NO_TIMEOUT); if (NULL == client) PL_FPrintError(err, "PR_Accept"); else { PR_fprintf(err, "Server accepting from "); (void)PrintAddress(&client_address); shared->threads += 1; (void)PR_CreateThread( PR_USER_THREAD, Servette, client, PR_PRIORITY_NORMAL, thread_scope, PR_UNJOINABLE_THREAD, 8 * 1024); } } while (PR_TRUE); } }} /* Server */static void Help(void){ PR_fprintf(err, "Usage: [-h] [<server>]\n"); PR_fprintf(err, "\t-s <n> Initial # of connections (default: 1)\n"); PR_fprintf(err, "\t-C <n> Set 'concurrency' (default: 1)\n"); PR_fprintf(err, "\t-b <nK> Client buffer size (default: 32k)\n"); PR_fprintf(err, "\t-B <nK> Transport recv/send buffer size (default: sys)\n"); PR_fprintf(err, "\t-G Use GLOBAL threads (default: LOCAL)\n"); PR_fprintf(err, "\t-X Use XTP transport (default: TCP)\n"); PR_fprintf(err, "\t-6 Use IPv6 (default: IPv4)\n"); PR_fprintf(err, "\t-h This message and nothing else\n"); PR_fprintf(err, "\t<server> DNS name of server\n"); PR_fprintf(err, "\t\tIf <server> is not specified, this host will be\n"); PR_fprintf(err, "\t\tthe server and not act as a client.\n");} /* Help */PRIntn main(PRIntn argc, char **argv){ PLOptStatus os; const char *server_name = NULL; PLOptState *opt = PL_CreateOptState(argc, argv, "hGX6C:b:s:B:"); err = PR_GetSpecialFD(PR_StandardError); while (PL_OPT_EOL != (os = PL_GetNextOpt(opt))) { if (PL_OPT_BAD == os) continue; switch (opt->option) { case 0: /* Name of server */ server_name = opt->value; break; case 'G': /* Globular threads */ thread_scope = PR_GLOBAL_THREAD; break; case 'X': /* Use XTP as the transport */ protocol = 36; break; case '6': /* Use IPv6 */ domain = PR_AF_INET6; break; case 's': /* initial_streams */ initial_streams = atoi(opt->value); break; case 'C': /* concurrency */ concurrency = atoi(opt->value); break; case 'b': /* buffer size */ buffer_size = 1024 * atoi(opt->value); break; case 'B': /* buffer size */ xport_buffer = 1024 * atoi(opt->value); break; case 'h': /* user wants some guidance */ default: Help(); /* so give him an earful */ return 2; /* but not a lot else */ } } PL_DestroyOptState(opt); shared = PR_NEWZAP(Shared); shared->ml = PR_NewLock(); PR_fprintf(err, "This machine is %s\n", (NULL == server_name) ? "the SERVER" : "a CLIENT"); PR_fprintf(err, "Transport being used is %s\n", (6 == protocol) ? "TCP" : "XTP"); if (PR_GLOBAL_THREAD == thread_scope) { if (1 != concurrency) { PR_fprintf(err, " **Concurrency > 1 and GLOBAL threads!?!?\n"); PR_fprintf(err, " **Ignoring concurrency\n"); concurrency = 1; } } if (1 != concurrency) { PR_SetConcurrency(concurrency); PR_fprintf(err, "Concurrency set to %u\n", concurrency); } PR_fprintf(err, "All threads will be %s\n", (PR_GLOBAL_THREAD == thread_scope) ? "GLOBAL" : "LOCAL"); PR_fprintf(err, "Client buffer size will be %u\n", buffer_size); if (-1 != xport_buffer) PR_fprintf( err, "Transport send & receive buffer size will be %u\n", xport_buffer); if (NULL == server_name) Server(); else Client(server_name);} /* main *//* thruput.c */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -