I was doing some casual profiling of some httpuv servers and noticed that the call stack was deeper than I expected. You can see in the flame graph below (for the "hello, world" example) that there is a tryCatch/eval stack between later::execCallbacks() and the actual call() method (anonymous here) for the server:
I eventually worked out that this tryCatch/eval setup is manually created in C++ code when evaluating an Rcpp::Function, in order to prevent longjmps. This might be well-known. However, it is also apparent from the flame graph that this particular stack seems to impose a significant amount of overhead on all requests, and I wondered if removing it could improve performance.
As it turns out, Rcpp has a not-very-well-advertised configuration option to avoid this in favour of newer C-level features of R, RCPP_USE_UNWIND_PROTECT (originally implemented by Lionel Henry, I believe). This flag is used by some existing packages, dplyr among them, so it probably has few downsides.
To illustrate the potential difference, I ran some load testing for the "hello, world" server against vanilla master:
I was doing some casual profiling of some
httpuv
servers and noticed that the call stack was deeper than I expected. You can see in the flame graph below (for the "hello, world" example) that there is atryCatch
/eval
stack betweenlater::execCallbacks()
and the actualcall()
method (anonymous here) for the server:I eventually worked out that this
tryCatch
/eval
setup is manually created in C++ code when evaluating anRcpp::Function
, in order to prevent longjmps. This might be well-known. However, it is also apparent from the flame graph that this particular stack seems to impose a significant amount of overhead on all requests, and I wondered if removing it could improve performance.As it turns out,
Rcpp
has a not-very-well-advertised configuration option to avoid this in favour of newer C-level features of R,RCPP_USE_UNWIND_PROTECT
(originally implemented by Lionel Henry, I believe). This flag is used by some existing packages,dplyr
among them, so it probably has few downsides.To illustrate the potential difference, I ran some load testing for the "hello, world" server against vanilla
master
:And with
PKG_CPPFLAGS += -DRCPP_USE_UNWIND_PROTECT
:As you can see, throughput is about 50% higher. The accompanying flame graph, showing the simplified stack, is below:
In light of this, I believe that you should consider building
httpuv
withRCPP_USE_UNWIND_PROTECT
by default, if possible.