OLD | NEW |
(Empty) | |
| 1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. |
| 4 |
| 5 #include "base/at_exit.h" |
| 6 #include "base/command_line.h" |
| 7 #include "base/message_loop.h" |
| 8 #include "base/singleton.h" |
| 9 #include "base/stats_counters.h" |
| 10 #include "base/string_util.h" |
| 11 #include "net/base/completion_callback.h" |
| 12 #include "net/base/io_buffer.h" |
| 13 #include "net/base/net_errors.h" |
| 14 #include "net/http/http_cache.h" |
| 15 #include "net/http/http_network_layer.h" |
| 16 #include "net/http/http_request_info.h" |
| 17 #include "net/http/http_transaction.h" |
| 18 #include "net/proxy/proxy_service.h" |
| 19 |
| 20 void usage(const char* program_name) { |
| 21 printf("usage: %s --url=<url> [--n=<clients>] [--stats] [--use_cache]\n", |
| 22 program_name); |
| 23 exit(1); |
| 24 } |
| 25 |
| 26 // Test Driver |
| 27 class Driver { |
| 28 public: |
| 29 Driver() |
| 30 : clients_(0) {} |
| 31 |
| 32 void ClientStarted() { clients_++; } |
| 33 void ClientStopped() { |
| 34 if (!--clients_) { |
| 35 MessageLoop::current()->Quit(); |
| 36 } |
| 37 } |
| 38 |
| 39 private: |
| 40 int clients_; |
| 41 }; |
| 42 |
| 43 // A network client |
| 44 class Client { |
| 45 public: |
| 46 Client(net::HttpTransactionFactory* factory, const std::string& url) : |
| 47 url_(url), |
| 48 transaction_(factory->CreateTransaction()), |
| 49 buffer_(new net::IOBuffer(kBufferSize)), |
| 50 ALLOW_THIS_IN_INITIALIZER_LIST( |
| 51 connect_callback_(this, &Client::OnConnectComplete)), |
| 52 ALLOW_THIS_IN_INITIALIZER_LIST( |
| 53 read_callback_(this, &Client::OnReadComplete)) { |
| 54 buffer_->AddRef(); |
| 55 driver_->ClientStarted(); |
| 56 request_info_.url = url_; |
| 57 request_info_.method = "GET"; |
| 58 int state = transaction_->Start(&request_info_, &connect_callback_); |
| 59 DCHECK(state == net::ERR_IO_PENDING); |
| 60 }; |
| 61 |
| 62 private: |
| 63 void OnConnectComplete(int result) { |
| 64 // Do work here. |
| 65 int state = transaction_->Read(buffer_.get(), kBufferSize, &read_callback_); |
| 66 if (state == net::ERR_IO_PENDING) |
| 67 return; // IO has started. |
| 68 if (state < 0) |
| 69 return; // ERROR! |
| 70 OnReadComplete(state); |
| 71 } |
| 72 |
| 73 void OnReadComplete(int result) { |
| 74 if (result == 0) { |
| 75 OnRequestComplete(result); |
| 76 return; |
| 77 } |
| 78 |
| 79 // Deal with received data here. |
| 80 static StatsCounter bytes_read("FetchClient.bytes_read"); |
| 81 bytes_read.Add(result); |
| 82 |
| 83 // Issue a read for more data. |
| 84 int state = transaction_->Read(buffer_.get(), kBufferSize, &read_callback_); |
| 85 if (state == net::ERR_IO_PENDING) |
| 86 return; // IO has started. |
| 87 if (state < 0) |
| 88 return; // ERROR! |
| 89 OnReadComplete(state); |
| 90 } |
| 91 |
| 92 void OnRequestComplete(int result) { |
| 93 static StatsCounter requests("FetchClient.requests"); |
| 94 requests.Increment(); |
| 95 driver_->ClientStopped(); |
| 96 printf("."); |
| 97 } |
| 98 |
| 99 static const int kBufferSize = (16 * 1024); |
| 100 GURL url_; |
| 101 net::HttpRequestInfo request_info_; |
| 102 scoped_ptr<net::HttpTransaction> transaction_; |
| 103 scoped_ptr<net::IOBuffer> buffer_; |
| 104 net::CompletionCallbackImpl<Client> connect_callback_; |
| 105 net::CompletionCallbackImpl<Client> read_callback_; |
| 106 Singleton<Driver> driver_; |
| 107 }; |
| 108 |
| 109 int main(int argc, char**argv) { |
| 110 base::AtExitManager exit; |
| 111 StatsTable table("fetchclient", 50, 1000); |
| 112 table.set_current(&table); |
| 113 |
| 114 CommandLine::Init(0, NULL); |
| 115 const CommandLine& parsed_command_line = *CommandLine::ForCurrentProcess(); |
| 116 std::string url = WideToASCII(parsed_command_line.GetSwitchValue(L"url")); |
| 117 if (!url.length()) |
| 118 usage(argv[0]); |
| 119 int client_limit = 1; |
| 120 if (parsed_command_line.HasSwitch(L"n")) |
| 121 StringToInt(WideToASCII(parsed_command_line.GetSwitchValue(L"n")), |
| 122 &client_limit); |
| 123 bool use_cache = parsed_command_line.HasSwitch(L"use-cache"); |
| 124 |
| 125 // Do work here. |
| 126 MessageLoop loop; |
| 127 |
| 128 scoped_ptr<net::ProxyService> proxy_service(net::ProxyService::CreateNull()); |
| 129 net::HttpTransactionFactory* factory = NULL; |
| 130 if (use_cache) |
| 131 factory = new net::HttpCache(proxy_service.get(), 0); |
| 132 else |
| 133 factory = new net::HttpNetworkLayer(proxy_service.get()); |
| 134 |
| 135 { |
| 136 StatsCounterTimer driver_time("FetchClient.total_time"); |
| 137 StatsScope<StatsCounterTimer> scope(driver_time); |
| 138 |
| 139 Client** clients = new Client*[client_limit]; |
| 140 for (int i = 0; i < client_limit; i++) |
| 141 clients[i] = new Client(factory, url); |
| 142 |
| 143 MessageLoop::current()->Run(); |
| 144 } |
| 145 |
| 146 // Print Statistics here. |
| 147 int num_clients = table.GetCounterValue("c:FetchClient.requests"); |
| 148 int test_time = table.GetCounterValue("t:FetchClient.total_time"); |
| 149 int bytes_read = table.GetCounterValue("c:FetchClient.bytes_read"); |
| 150 |
| 151 printf("\n"); |
| 152 printf("Clients : %d\n", num_clients); |
| 153 printf("Time : %dms\n", test_time); |
| 154 printf("Bytes Read : %d\n", bytes_read); |
| 155 if (test_time > 0) { |
| 156 const char *units = "bps"; |
| 157 double bps = static_cast<float>(bytes_read * 8) / |
| 158 (static_cast<float>(test_time) / 1000.0); |
| 159 |
| 160 if (bps > (1024*1024)) { |
| 161 bps /= (1024*1024); |
| 162 units = "Mbps"; |
| 163 } else if (bps > 1024) { |
| 164 bps /= 1024; |
| 165 units = "Kbps"; |
| 166 } |
| 167 printf("Bandwidth : %.2f%s\n", bps, units); |
| 168 } |
| 169 |
| 170 if (parsed_command_line.HasSwitch(L"stats")) { |
| 171 // Dump the stats table. |
| 172 printf("<stats>\n"); |
| 173 int counter_max = table.GetMaxCounters(); |
| 174 for (int index=0; index < counter_max; index++) { |
| 175 std::string name(table.GetRowName(index)); |
| 176 if (name.length() > 0) { |
| 177 int value = table.GetRowValue(index); |
| 178 printf("%s:\t%d\n", name.c_str(), value); |
| 179 |
| 180 } |
| 181 } |
| 182 printf("</stats>\n"); |
| 183 } |
| 184 return 0; |
| 185 } |
OLD | NEW |