#!/usr/bin/env bx use b cstr root = "/www/sam.test" cstr test_dir = "test" int n_reps = 20 int n_parallel = 128 int n_files = 5000 int count = 0 int bytes = 0 cstr url_root = "http://sam.test" cstr host = "sam.test" int port = 80 num min_size = 1 # in kb num max_size = 10*1024 # in kb boolean counting = 0 num rand_size(num min_size, num max_size) num ln_min = log(min_size) num ln_max = log(max_size) num p = Rand() num x = 1-sqrt(1-p) num s = exp((ln_max - ln_min)*x + ln_min) return s create_files(vec *v) for(i, 0, n_files) cstr dir = format("%d/%d", randi(0, 10), randi(0, 10)) Mkdirs(dir) cstr name repeat name = format("%s/%d", dir, randi(0, 1000000)) if !exists(name) break Free(name) int size = (int)rand_size(min_size, max_size) Sayf("dd bs=1024 count=%d if=/dev/urandom of=%s", size, name) Systemf("dd bs=1024 count=%d if=/dev/urandom of=%s", size, name) Free(dir) vec_push(v, name) # TODO internal dd-like function Main() if args && arg[0][0] == '-' usage("[port [n_reps [n_parallel [n_files]]]]") if args >= 1 port = atoi(arg[0]) if args >= 2 n_reps = atoi(arg[1]) if args >= 3 n_parallel = atoi(arg[2]) if args >= 4 n_files = atoi(arg[3]) block_size = 16 * 1024 new(v, vec, cstr, n_files+1) cstr cwd = Getcwd() Chdir(root) boolean create = !exists(test_dir) if create mkdir(test_dir) Chdir(test_dir) if create create_files(v) else find_vec_files(".", v) sched_init() # sched_busy = 16 # sched_delay = 0.000001 new(b, buffer, 256) system_quote(cwd, b) Free(cwd) ; cwd = buf0(b) int i = 0 repeat(n_reps) # Systemf("wc -l < %s/errlog >> %s/errlog-lines", cwd, cwd) new(st, starter, v, i, n_parallel) start(st) run() i += n_parallel while i >= n_files i -= n_files fprintf(stderr, "\n") # TODO sched needs to put finished processes into a "zombie queue" sort of thing proc starter(vec *v, int i, int n) for ; n ; --n New(c, http_test, *(cstr *)v(v, i)) start(c) ++i if i >= n_files i -= n_files repeat(10) yield() # sched->now = rtime() # state num t = sched->now + 0.02 # # FIXME don't busy wait, use a timeout! # while (sched->now = rtime()) < t # yield() proc http_test(cstr file) port buffer in port buffer out state cstr s state size_t l state boolean keep_alive = 0 state off_t len = 0 state reader r state writer w state cstr url = format("%s/%s/%s", url_root, test_dir, file) # Sayf("%s\tstart", url) connect_nb_tcp(sk, host, port) # Sayf("%s\tconn", url) init(&r, reader, sk->fd) init(&w, writer, sk->fd) sh(buffer, &r, This) sh(buffer, This, &w) init(&in, buffer, block_size) init(&out, buffer, block_size) start(&r) ; start(&w) # warn("GET %s HTTP/1.0", url) bsayf(out, "GET %s HTTP/1.0\r\n\r", url) bflush(out) # push(out) # shutdown it # Sayf("%s\treq", url) breadln(in) if !buflen(&in) warn("no response") quit s = buf0(&in) l = strlen(s)+1 cstr_dos_to_unix(s) s = Strchr(s, ' ')+1 int status = atoi(s) if status != 200 warn("http_test failed") quit buffer_shift(&in, l) # Sayf("%s\tresp", url) # read headers repeat breadln(in) if !buflen(&in) warn("closed while reading headers") quit s = buf0(&in) l = strlen(s)+1 cstr_dos_to_unix(s) if !*s buffer_shift(&in, l) break # Sayf("%s\thdr %s", url, s) cstr *words = split(s, ':', 2) if arylen(words) != 2 Free(words) warn("received bad header %s", s) quit cstr key = words[0], val = words[1] Free(words) while isspace(val[0]) ++val # warn("header: %s: %s", key, val) if !strcasecmp(key, "Content-Length") len = atoll(val) eif !strcasecmp(key, "Connection") if !strcasecmp(val, "close") keep_alive = 0 eif !strcasecmp(val, "Keep-Alive") keep_alive = 1 buffer_shift(&in, l) # Sayf("%s\theaders %lld", url, len) discard_content() # if counting # fprintf(stderr, "%d\r", ++count) # Sayf("%s\tdone", url) # fflush(stdout) # warn("req finished okay: %lld bytes", len) quit Free(url) buffer_free(&in) buffer_free(&out) rm_fd(sk->fd) sock_free(sk) Free(sk) Free(This) stop def discard_content() state int n_recvd = 0 if len == 0 error("response has no body") # Sayf("%s\tabout to discard %lld", url, len) while n_recvd < len bread(in, imin(block_size, len-n_recvd)) l = buflen(&in) n_recvd += l bufclr(&in) # Sayf("%s\tdiscarding %d", url, n_recvd) if n_recvd != len error("wrong number of bytes received: %d != %d", buflen(&in), (int)len) bytes += len