bench.c (3057B)
1 // A benchmark adapted from https://github.com/h2o/picohttpparser 2 3 #define _GNU_SOURCE 1 4 5 #include <assert.h> 6 #include <stdio.h> 7 #include <time.h> 8 #include <string.h> 9 10 #define HTTPP_IMPLEMENTATION 11 #include "httpp.h" 12 13 #include "picohttpparser.h" 14 #include "picohttpparser.c" 15 16 #include "mblhttp.h" 17 18 #define REQ \ 19 "GET /cookies HTTP/1.1\r\n" \ 20 "Host: 127.0.0.1:8090\r\n" \ 21 "Connection: keep-alive\r\n" \ 22 "Cache-Control: max-age=0\r\n" \ 23 "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\r\n" \ 24 "User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.17 (KHTML, like Gecko) Chrome/24.0.1312.56 Safari/537.17\r\n" \ 25 "Accept-Encoding: gzip,deflate,sdch\r\n" \ 26 "Accept-Language: en-US,en;q=0.8\r\n" \ 27 "Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.3\r\n" \ 28 "Cookie: name=wookie\r\n" \ 29 "\r\n" 30 31 #define ITERATIONS 10000000 32 33 double now_seconds() 34 { 35 struct timespec ts; 36 clock_gettime(CLOCK_MONOTONIC, &ts); 37 return ts.tv_sec + ts.tv_nsec / 1e9; 38 } 39 40 static double 41 bench_httpp(char *req, size_t len) 42 { 43 double t0 = now_seconds(); 44 45 for (int i = 0; i < ITERATIONS; i++) { 46 httpp_req_t *result = httpp_parse_request(req); 47 assert(result); 48 49 httpp_req_free(result); 50 } 51 52 double t1 = now_seconds(); 53 54 return t1 - t0; 55 } 56 57 static double 58 bench_phr(char *req, size_t len) 59 { 60 double t0 = now_seconds(); 61 62 size_t num_hdrs = 64; 63 struct phr_header hdrs[num_hdrs]; 64 65 char const *method, *path; 66 size_t method_len, path_len; 67 int minor_version; 68 69 for (int i = 0; i < ITERATIONS; i++) { 70 int res = phr_parse_request(req, len, 71 &method, &method_len, 72 &path, &path_len, 73 &minor_version, 74 hdrs, &num_hdrs, 75 0); 76 assert(res > 0); 77 } 78 79 double t1 = now_seconds(); 80 81 return t1 - t0; 82 } 83 84 static double 85 bench_mbl(char *req, size_t len) 86 { 87 double t0 = now_seconds(); 88 89 size_t num_hdrs = 64; 90 struct mbl_http_header hdrs[num_hdrs]; 91 92 struct mbl_http_msg msg; 93 94 for (int i = 0; i < ITERATIONS; i++) { 95 int res = mbl_http_msg_parse(&msg, req, len, hdrs, num_hdrs); 96 assert(res >= 0); 97 } 98 99 double t1 = now_seconds(); 100 101 #if 1 102 struct mbl_http_header *hdr = mbl_http_msg_find_header(&msg, "hOST", 4); 103 assert(hdr); 104 105 printf("parsed http request line: %.*s\n", 106 msg.request_line.len, msg.request_line.ptr); 107 108 printf("parsed http request headers: %zu/%zu\n", 109 msg.hdrs_len, msg.hdrs_cap); 110 for (size_t i = 0; i < msg.hdrs_len; i++) { 111 printf("\t%zu = { key: \"%.*s\", val: \"%.*s\" }\n", 112 i, msg.hdrs[i].key.len, msg.hdrs[i].key.ptr, 113 msg.hdrs[i].val.len, msg.hdrs[i].val.ptr); 114 } 115 116 printf("parsed http request body: %d bytes\n", msg.body.len); 117 printf("%.*s\n", msg.body.len, (char *) msg.body.ptr); 118 #endif 119 120 return t1 - t0; 121 } 122 123 static void 124 stats(char const *name, double elapsed) 125 { 126 printf("Benchmarking: %s\n", name); 127 printf("Elapsed %f seconds.\n", elapsed); 128 printf("Requests per second ≈ %.2f \n", ITERATIONS / elapsed); 129 } 130 131 int 132 main() 133 { 134 char* req = REQ; 135 size_t len = strlen(REQ); 136 137 stats("httpp", bench_httpp(req, len)); 138 stats("phr", bench_phr(req, len)); 139 stats("mbl", bench_mbl(req, len)); 140 141 return 0; 142 }