httpp-benchmark

httpp-benchmark.git
git clone git://git.lenczewski.org/httpp-benchmark.git
Log | Files | Refs | README | LICENSE

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 }