Back to index

nordugrid-arc-nox  1.1.0~rc6
perftest_msgsize.cpp
Go to the documentation of this file.
00001 // -*- indent-tabs-mode: nil -*-
00002 
00003 #ifdef HAVE_CONFIG_H
00004 #include <config.h>
00005 #endif
00006 
00007 // perftest.cpp
00008 
00009 #include <iostream>
00010 #include <fstream>
00011 #include <sstream>
00012 #include <string>
00013 #include <stdlib.h>
00014 #include <glibmm/thread.h>
00015 #include <glibmm/timer.h>
00016 
00017 #include <arc/GUID.h>
00018 #include <arc/ArcConfig.h>
00019 #include <arc/Logger.h>
00020 #include <arc/URL.h>
00021 #include <arc/message/PayloadSOAP.h>
00022 #include <arc/message/MCC.h>
00023 #include <arc/client/ClientInterface.h>
00024 
00025 // Some global shared variables...
00026 Glib::Mutex* mutex;
00027 bool run;
00028 int finishedThreads;
00029 unsigned long completedRequests;
00030 unsigned long failedRequests;
00031 unsigned long totalRequests;
00032 Glib::TimeVal completedTime;
00033 Glib::TimeVal failedTime;
00034 Glib::TimeVal totalTime;
00035 std::string url_str;
00036 bool alwaysReconnect = false;
00037 bool printTimings = false;
00038 bool tcpNoDelay = false;
00039 bool fixedMsgSize = false;
00040 int start;
00041 int stop;
00042 int steplength;
00043 int msgSize;
00044 
00045 // Round off a double to an integer.
00046 int Round(double x){
00047   return int(x+0.5);
00048 }
00049 
00050 // Send requests and collect statistics.
00051 void sendRequests(){
00052   // Some variables...
00053   unsigned long completedRequests = 0;
00054   unsigned long failedRequests = 0;
00055   Glib::TimeVal completedTime(0,0);
00056   Glib::TimeVal failedTime(0,0);
00057   Glib::TimeVal tBefore;
00058   Glib::TimeVal tAfter;
00059   bool connected;
00060 
00061   //std::string url_str("https://127.0.0.1:60000/echo");
00062   Arc::URL url(url_str);
00063   if(tcpNoDelay) url.AddOption("tcpnodelay","yes");
00064   Arc::MCCConfig mcc_cfg;
00065   mcc_cfg.AddPrivateKey("../echo/testuserkey-nopass.pem");
00066   mcc_cfg.AddCertificate("../echo/testusercert.pem");
00067   mcc_cfg.AddCAFile("../echo/testcacert.pem");
00068   mcc_cfg.AddCADir("../echo/certificates");
00069 
00070   Arc::NS echo_ns; echo_ns["echo"]="http://www.nordugrid.org/schemas/echo";
00071   
00072   std::string size;
00073   Arc::ClientSOAP *client = NULL;
00074   while(run){
00075     connected=false;
00076     for(int i=start; i<stop; i+=steplength){
00077       // Create a Client.
00078       if(!connected){
00079         if(client) delete client;
00080         client = NULL;
00081         client = new Arc::ClientSOAP(mcc_cfg,url,60);
00082         connected = true;
00083       }
00084       
00085       // Prepare the request.
00086       Arc::PayloadSOAP req(echo_ns);
00087       std::stringstream sstr;
00088       fixedMsgSize ? sstr << msgSize : sstr << i;
00089       size = sstr.str();
00090       //req.NewChild("echo").NewChild("say")="HELLO";
00091       req.NewChild("size").NewChild("size")=size;
00092       // Send the request and time it.
00093       tBefore.assign_current_time();
00094       Arc::PayloadSOAP* resp = NULL;
00095        
00096       //std::string str;
00097       //req.GetXML(str);
00098       //std::cout<<"request: "<<str<<std::endl;
00099       Arc::MCC_Status status = client->process(&req,&resp);
00100       
00101       tAfter.assign_current_time();
00102       
00103       if(!status) {
00104         // Request failed.
00105         failedRequests++;
00106         failedTime+=tAfter-tBefore;
00107         connected=false;
00108       } else {
00109         if(resp == NULL) {
00110           // Response was not SOAP or no response at all.
00111           failedRequests++;
00112           failedTime+=tAfter-tBefore;
00113           connected=false;
00114         } else {
00115           //std::string xml;
00116           //resp->GetXML(xml);
00117           if (std::string((*resp)["echoResponse"]["hear"]).size()==0){
00118             // The response was not what it should be.
00119             failedRequests++;
00120             failedTime+=tAfter-tBefore;
00121             connected=false;
00122           }
00123           else{
00124             // Everything worked just fine!
00125             completedRequests++;
00126             completedTime+=tAfter-tBefore;
00127             if (printTimings) std::cout << completedRequests << " " << size << " " << tAfter.as_double()-tBefore.as_double() << std::endl;
00128           }
00129         }
00130       }
00131       if(resp) delete resp;
00132       if(alwaysReconnect) connected=false;
00133     }
00134     if(client) delete client;
00135   
00136   }
00137 
00138   // Update global variables.
00139   Glib::Mutex::Lock lock(*mutex);
00140   ::completedRequests+=completedRequests;
00141   ::failedRequests+=failedRequests;
00142   ::completedTime+=completedTime;
00143   ::failedTime+=failedTime;
00144   finishedThreads++;
00145   std::cout << "Number of finished threads: " << finishedThreads << std::endl;
00146 }
00147 
00148 int main(int argc, char* argv[]){
00149   // Some variables...
00150   int numberOfThreads;
00151   int duration;
00152   int i;
00153   Glib::Thread** threads;
00154   const char* config_file = NULL;
00155   int debug_level = -1;
00156   Arc::LogStream logcerr(std::cerr);
00157 
00158   // Process options - quick hack, must use Glib options later
00159   while(argc >= 7) {
00160     if(strcmp(argv[1],"-c") == 0) {
00161       config_file = argv[2];
00162       argv[2]=argv[0]; argv+=2; argc-=2;
00163     } else if(strcmp(argv[1],"-d") == 0) {
00164       debug_level=Arc::string_to_level(argv[2]);
00165       argv[2]=argv[0]; argv+=2; argc-=2;
00166     } else if(strcmp(argv[1],"-f") == 0) {
00167       fixedMsgSize = true; msgSize=atoi(argv[2]);
00168       argv[2]=argv[0]; argv+=2; argc-=2;
00169     } else if(strcmp(argv[1],"-r") == 0) {
00170       alwaysReconnect=true; argv+=1; argc-=1;
00171     } else if(strcmp(argv[1],"-v") == 0) {
00172       printTimings=true; argv+=1; argc-=1;
00173     } else if(strcmp(argv[1],"-t") == 0) {
00174       tcpNoDelay=true; argv+=1; argc-=1;
00175     } else {
00176       break;
00177     };
00178   } 
00179   if(debug_level >= 0) {
00180     Arc::Logger::getRootLogger().setThreshold((Arc::LogLevel)debug_level);
00181     Arc::Logger::getRootLogger().addDestination(logcerr);
00182   }
00183   // Extract command line arguments.
00184   if (argc!=7){
00185     std::cerr << "Wrong number of arguments!" << std::endl
00186               << std::endl
00187               << "Usage:" << std::endl
00188               << "perftest [-c config] [-d debug] [-r] [-t] [-v] url threads duration start stop steplength" << std::endl
00189               << std::endl
00190               << "Arguments:" << std::endl
00191               << "url        The url of the service." << std::endl
00192               << "threads   The number of concurrent requests." << std::endl
00193               << "duration  The duration of the test in seconds." << std::endl
00194               << "start      The size of the first response from the echo service." << std::endl
00195               << "stop       The size of the last response from the echo service." << std::endl
00196               << "steplength The increase of size per call to the echo service." << std::endl
00197               << "-c config  The file containing client chain XML configuration with " << std::endl
00198               << "           'soap' entry point and HOSTNAME, PORTNUMBER and PATH " << std::endl
00199               << "            keyword for hostname, port and HTTP path of 'echo' service." << std::endl
00200               << "-d debug   The textual representation of desired debug level. Available " << std::endl
00201               << "            levels: DEBUG, VERBOSE, INFO, WARNING, ERROR, FATAL." << std::endl
00202               << "-r         If specified close connection and reconnect after " << std::endl
00203               << "            every request." << std::endl
00204               << "-t         Toggles TCP_NODELAY option " << std::endl
00205               << "-f size    Fixed message size " << std::endl
00206               << "-v         If specified print out timings for each iteration " << std::endl;
00207     exit(EXIT_FAILURE);
00208   }
00209   url_str = std::string(argv[1]);
00210   numberOfThreads = atoi(argv[2]);
00211   duration = atoi(argv[3]);
00212   start = atoi(argv[4]);
00213   stop = atoi(argv[5]);
00214   steplength = atoi(argv[6]);
00215 
00216   // Start threads.
00217   run=true;
00218   finishedThreads=0;
00219   //Glib::thread_init();
00220   mutex=new Glib::Mutex;
00221   threads = new Glib::Thread*[numberOfThreads];
00222   for (i=0; i<numberOfThreads; i++)
00223     threads[i]=Glib::Thread::create(sigc::ptr_fun(sendRequests),true);
00224 
00225   // Sleep while the threads are working.
00226   Glib::usleep(duration*1000000);
00227 
00228   // Stop the threads
00229   run=false;
00230   while(finishedThreads<numberOfThreads)
00231     Glib::usleep(100000);
00232 
00233   // Print the result of the test.
00234   Glib::Mutex::Lock lock(*mutex);
00235   totalRequests = completedRequests+failedRequests;
00236   totalTime = completedTime+failedTime;
00237   std::cout << "========================================" << std::endl;
00238   std::cout << "URL: "
00239             << url_str << std::endl;
00240   std::cout << "Number of threads: "
00241             << numberOfThreads << std::endl;
00242   std::cout << "Duration: "
00243             << duration << " s" << std::endl;
00244   std::cout << "Number of requests: "
00245             << totalRequests << std::endl;
00246   std::cout << "Completed requests: "
00247             << completedRequests << " ("
00248             << Round(completedRequests*100.0/totalRequests)
00249             << "%)" << std::endl;
00250   std::cout << "Failed requests: "
00251             << failedRequests << " ("
00252             << Round(failedRequests*100.0/totalRequests)
00253             << "%)" << std::endl;
00254   std::cout << "Completed requests per second: "
00255             << Round(completedRequests/duration)
00256             << std::endl;
00257   std::cout << "Average response time for all requests: "
00258             << Round(1000*totalTime.as_double()/totalRequests)
00259             << " ms" << std::endl;
00260   if (completedRequests!=0)
00261     std::cout << "Average response time for completed requests: "
00262               << Round(1000*completedTime.as_double()/completedRequests)
00263               << " ms" << std::endl;
00264   if (failedRequests!=0)
00265     std::cout << "Average response time for failed requests: "
00266               << Round(1000*failedTime.as_double()/failedRequests)
00267               << " ms" << std::endl;
00268   std::cout << "========================================" << std::endl;
00269 
00270   return 0;
00271 }