roundtrip_tcp.cc revision be081f78
191852b37SShuo Chen#include "InetAddress.h" 291852b37SShuo Chen#include "TcpStream.h" 391852b37SShuo Chen 4be081f78SShuo Chen#include <limits> 591852b37SShuo Chen#include <memory> 691852b37SShuo Chen#include <unistd.h> 791852b37SShuo Chen#include <stdlib.h> 891852b37SShuo Chen#include <stdio.h> 991852b37SShuo Chen#include <time.h> 1091852b37SShuo Chen 1191852b37SShuo Chen#include <vector> 1291852b37SShuo Chen 1391852b37SShuo Chenint64_t kNanos = 1e9; 1491852b37SShuo Chenint64_t clock_diff(struct timespec x, struct timespec y) 1591852b37SShuo Chen{ 1691852b37SShuo Chen return (x.tv_sec - y.tv_sec) * kNanos + x.tv_nsec - y.tv_nsec; 1791852b37SShuo Chen} 1891852b37SShuo Chen 1991852b37SShuo Chenstruct timespec get_time() 2091852b37SShuo Chen{ 2191852b37SShuo Chen struct timespec now; 2291852b37SShuo Chen clock_gettime(CLOCK_MONOTONIC, &now); 2391852b37SShuo Chen return now; 2491852b37SShuo Chen} 2591852b37SShuo Chen 2691852b37SShuo Chenstruct Sample 2791852b37SShuo Chen{ 2891852b37SShuo Chen int index; 2991852b37SShuo Chen int64_t start_nano; 3091852b37SShuo Chen int64_t rtt_nano; 3191852b37SShuo Chen}; 3291852b37SShuo Chen 33be081f78SShuo Chenstd::vector<Sample> run(const char* host, int delay_ms, int length_s, int batch, int payload_size, bool silent) 3491852b37SShuo Chen{ 35be081f78SShuo Chen const struct timespec start = get_time(); 3691852b37SShuo Chen std::vector<Sample> rtts; 3791852b37SShuo Chen 3891852b37SShuo Chen InetAddress addr; 3991852b37SShuo Chen if (!InetAddress::resolve(host, 3007, &addr)) 4091852b37SShuo Chen { 4191852b37SShuo Chen printf("Unable to resolve %s\n", host); 4291852b37SShuo Chen return rtts; 4391852b37SShuo Chen } 4491852b37SShuo Chen 4591852b37SShuo Chen // printf("connecting to %s\n", addr.toIpPort().c_str()); 4691852b37SShuo Chen TcpStreamPtr stream(TcpStream::connect(addr)); 4791852b37SShuo Chen if (!stream) 4891852b37SShuo Chen { 4991852b37SShuo Chen printf("Unable to connect %s\n", addr.toIpPort().c_str()); 5091852b37SShuo Chen perror(""); 5191852b37SShuo Chen return rtts; 5291852b37SShuo Chen } 5391852b37SShuo Chen 5491852b37SShuo Chen std::unique_ptr<char[]> payload(new char[payload_size]); 55be081f78SShuo Chen int64_t count = 0, sum_rtt = 0; 56be081f78SShuo Chen int64_t min_rtt = std::numeric_limits<int64_t>::max(), max_rtt = 0; 5791852b37SShuo Chen 5891852b37SShuo Chen while (true) { 59be081f78SShuo Chen const struct timespec batch_start = get_time(); 60be081f78SShuo Chen double elapsed_s = (double)clock_diff(batch_start, start) / kNanos; 61be081f78SShuo Chen if (elapsed_s >= length_s) { 62be081f78SShuo Chen if (silent && count > 0) { 63be081f78SShuo Chen printf("count %ld, avg rtt %.2fus, min %.2fus, max %.2fus\n", 64be081f78SShuo Chen count, sum_rtt / 1e3 / count, min_rtt / 1e3, max_rtt / 1e3); 65be081f78SShuo Chen } 6691852b37SShuo Chen break; 67be081f78SShuo Chen } 6891852b37SShuo Chen 6991852b37SShuo Chen for (int i = 0; i < batch; ++i) { 70be081f78SShuo Chen const struct timespec before = get_time(); 7191852b37SShuo Chen int nw = stream->sendAll(payload.get(), payload_size); 7291852b37SShuo Chen if (nw != payload_size) 7391852b37SShuo Chen return rtts; 7491852b37SShuo Chen int nr = stream->receiveAll(payload.get(), payload_size); 7591852b37SShuo Chen if (nr != payload_size) 7691852b37SShuo Chen return rtts; 77be081f78SShuo Chen const struct timespec after = get_time(); 78be081f78SShuo Chen int64_t rtt = clock_diff(after, before); 79be081f78SShuo Chen ++count; 80be081f78SShuo Chen sum_rtt += rtt; 81be081f78SShuo Chen if (rtt > max_rtt) 82be081f78SShuo Chen max_rtt = rtt; 83be081f78SShuo Chen if (rtt < min_rtt) 84be081f78SShuo Chen min_rtt = rtt; 85be081f78SShuo Chen 8691852b37SShuo Chen Sample s = { 8791852b37SShuo Chen .index = i, 88be081f78SShuo Chen .rtt_nano = rtt, 8991852b37SShuo Chen }; 9091852b37SShuo Chen if (i == 0) 9191852b37SShuo Chen s.start_nano = clock_diff(before, start); 9291852b37SShuo Chen else 93be081f78SShuo Chen s.start_nano = clock_diff(before, batch_start); 94be081f78SShuo Chen if (!silent) 95be081f78SShuo Chen rtts.push_back(s); 9691852b37SShuo Chen } 9791852b37SShuo Chen 9891852b37SShuo Chen if (delay_ms > 0) { 9991852b37SShuo Chen ::usleep(delay_ms * 1000); 10091852b37SShuo Chen } 10191852b37SShuo Chen } 10291852b37SShuo Chen return rtts; 10391852b37SShuo Chen} 10491852b37SShuo Chen 10591852b37SShuo Chenint main(int argc, char* argv[]) 10691852b37SShuo Chen{ 10791852b37SShuo Chen int opt; 10891852b37SShuo Chen int delay = 0, length = 3, batch = 4, payload = 1; 10991852b37SShuo Chen bool silent = false; 11091852b37SShuo Chen while ((opt = getopt(argc, argv, "b:d:l:p:s")) != -1) { 11191852b37SShuo Chen switch (opt) { 11291852b37SShuo Chen case 'b': 11391852b37SShuo Chen batch = atoi(optarg); 11491852b37SShuo Chen break; 11591852b37SShuo Chen case 'd': 11691852b37SShuo Chen delay = atoi(optarg); 11791852b37SShuo Chen break; 11891852b37SShuo Chen case 'l': 11991852b37SShuo Chen length = atoi(optarg); 12091852b37SShuo Chen break; 12191852b37SShuo Chen case 'p': 12291852b37SShuo Chen payload = atoi(optarg); 12391852b37SShuo Chen break; 12491852b37SShuo Chen case 's': 12591852b37SShuo Chen silent = true; 12691852b37SShuo Chen break; 12791852b37SShuo Chen default: 12891852b37SShuo Chen ; 12991852b37SShuo Chen } 13091852b37SShuo Chen } 13191852b37SShuo Chen if (optind >= argc) { 13291852b37SShuo Chen fprintf(stderr, "Usage:\nroundtrip_tcp [-b batch_size] [-d delay_ms] [-l length_in_seconds] echo_server_host\n"); 13391852b37SShuo Chen return 1; 13491852b37SShuo Chen } 135be081f78SShuo Chen if (batch < 1) { 136be081f78SShuo Chen batch = 1; 137be081f78SShuo Chen } 138be081f78SShuo Chen if (delay < 0) { 139be081f78SShuo Chen delay = 0; 140be081f78SShuo Chen } 141be081f78SShuo Chen if (payload < 1) { 142be081f78SShuo Chen payload = 1; 143be081f78SShuo Chen } 144be081f78SShuo Chen 145be081f78SShuo Chen std::vector<Sample> rtts = run(argv[optind], delay, length, batch, payload, silent); 14691852b37SShuo Chen if (!silent) { 147be081f78SShuo Chen printf("index start rtt\n"); 14891852b37SShuo Chen for (Sample s : rtts) { 14991852b37SShuo Chen printf("%d %ld %ld\n", s.index, s.start_nano, s.rtt_nano); 15091852b37SShuo Chen } 15191852b37SShuo Chen } 15291852b37SShuo Chen} 153