Issue #146 brought interesting discovery.
@s-u I actually haven't check the R benchmark code from #146. I was pretty sure that the main issue was due to fork overhead (which was somewhat aligned with my benchmarks here).
However I've run your code and indeed the fork overhead is very small. And that pointed me to the real source of why things are pretty slow when keep-alive is disabled: R's byte compiler. The "issue" here is that it seems compile .http.request and functions which are used inside it during every invocation. And since each request is handled in a fresh fork, it compiles it every time which adds significant overhead. I was suspecting this and tried to mitigate it here, but it seems it is not enough.
Consider following (pure Rserve) example:
calc_fib = function(n) {
if (n < 0L) stop("n should be >= 0")
if (n == 0L) return(0L)
if (n == 1L || n == 2L) return(1L)
x = rep(1L, n)
for (i in 3L:n) x[[i]] = x[[i - 1]] + x[[i - 2]]
x[[n]]
}
.http.request <- function(path, query, body, headers) {
n = query[["n"]]
n = as.integer(n)
list(charToRaw(as.character(calc_fib(n))), "text/plain")
}
Rserve:::run.Rserve(http.port=8092)
Testing with disabled JIT and disabled keep-alive
R_ENABLE_JIT=0 Rscript bench.R
./apib -c 1 -d 1 -k 0 http://localhost:8092/fib?n=10
gives around 550 req/s
Testing with enabled JIT and disabled keep-alive
R_ENABLE_JIT=3 Rscript bench.R
./apib -c 1 -d 1 -k 0 http://localhost:8092/fib?n=10
gives around 25 req/s
@s-u do you have any ideas on how to mitigate this apart from disabling byte compiler? (I don't really have an idea on how R's byte compiler works)
Issue #146 brought interesting discovery.
@s-u I actually haven't check the R benchmark code from #146. I was pretty sure that the main issue was due to fork overhead (which was somewhat aligned with my benchmarks here).
However I've run your code and indeed the fork overhead is very small. And that pointed me to the real source of why things are pretty slow when keep-alive is disabled: R's byte compiler. The "issue" here is that it seems compile
.http.requestand functions which are used inside it during every invocation. And since each request is handled in a fresh fork, it compiles it every time which adds significant overhead. I was suspecting this and tried to mitigate it here, but it seems it is not enough.Consider following (pure Rserve) example:
Testing with disabled JIT and disabled
keep-alivegives around 550 req/s
Testing with enabled JIT and disabled
keep-alivegives around 25 req/s
@s-u do you have any ideas on how to mitigate this apart from disabling byte compiler? (I don't really have an idea on how R's byte compiler works)