Back to index

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