plumber is the most popular API development tool in R. RestRserve has already been added in #3255.
This project compare performance based on 3 routes :
- GET /, SHOULD return a successful status code and an empty string
- GET /user/:id, SHOULD return a successful status code and the id
- POST /user, SHOULD return a successful status code and an empty string
Gently ping authors: @trestletech, @schloerke, @cpsievert, @meztez
Thanks @t-wojciech.
Waiting for explicit consent, or no opposition from any author 馃槢 to start working on it
@waghanza 馃憤
The dev version supports async. If installing from master (or >= v1.0.0), don't know if adding async support as another test would be interesting to compare
Something like:
#* @get /user/<id>
function(id) {
promises::promise(~ {later::later(~ resolve(id), 0) })
}
Edit: 9/15 @t-wojciech
Simpler code: (No need to get later involved)
#* @get /user/<id>
function(id) {
promises::promise_resolve(id)
}
plumber 1.0.0 in on CRAN now.
I was about to add this too... as RestRServe has already been added. I would definitely like to see the difference. But the benchmarks haven't been updated for over a month.
@t-wojciech Thinking on this some more, I want to be sure we are actually testing plumber and not the filters or serializers.
I've added a test file below to compare how fast the core of plumber is, with and without filters and serializers. Routes that end in default test using filters and a serializer. The testing routes test the core plumber response time.
# plumber.R
# GET /, SHOULD return a successful status code and an empty string
# GET /user/:id, SHOULD return a successful status code and the id
# POST /user, SHOULD return a successful status code and an empty string
named_empty_headers <- setNames(list(), character(0))
#* @preempt __first__
#* @get /
function(res) {
# https://github.com/rstudio/httpuv/issues/195
res$headers <- named_empty_headers
res
}
#* @serializer contentType list(type = "text/plain")
#* @get /default
function() {
""
}
#* @preempt __first__
#* @get /user/<id>
function(res, id) {
# https://github.com/rstudio/httpuv/issues/195
res$headers <- named_empty_headers
res$body <- id
res
}
#* @serializer contentType list(type = "text/plain")
#* @get /user/<id>/default
function(id) {
id
}
#* @preempt __first__
#* @post /user
function(res) {
# https://github.com/rstudio/httpuv/issues/195
res$headers <- named_empty_headers
res
}
#* @serializer contentType list(type = "text/plain")
#* @post /user/default
function() {
""
}
Show that there is a difference in the routes...
library(plumber)
# bring in `make_req()`
source("https://raw.githubusercontent.com/rstudio/plumber/4714945222c8ef5198f8f7a51ba65163ba8611e5/tests/testthat/helper-mock-request.R")
# parse plumber file
pr <- plumb("./plumber.R")
# test
microbenchmark::microbenchmark(
"/" = pr$call(make_req("GET", "/")),
"/default" = pr$call(make_req("GET", "/default")),
"/user/123" = pr$call(make_req("GET", "/user/123")),
"/user/123/default" = pr$call(make_req("GET", "/user/123/default")),
"/user" = pr$call(make_req("POST", "/user")),
"/user/default" = pr$call(make_req("POST", "/user/default"))
)
#> Unit: microseconds
#> expr min lq mean median uq max neval cld
#> / 402.207 497.5255 569.6792 540.931 621.0600 925.413 100 a
#> /default 1030.028 1247.8415 1426.8818 1311.467 1501.7705 7194.458 100 bc
#> /user/123 466.439 566.5340 634.3087 592.425 650.7055 1147.150 100 a
#> /user/123/default 1139.246 1290.8250 1488.4355 1352.736 1545.6525 7111.835 100 c
#> /user 398.733 506.4655 578.7242 547.862 602.8700 1109.749 100 a
#> /user/default 1112.267 1162.3905 1310.6001 1244.106 1385.1605 2174.182 100 b
...at least 50% faster if filters and serializers are not used.
I'll make a PR soon copying the style of https://github.com/the-benchmarker/web-frameworks/pull/3255
Most helpful comment
@t-wojciech Thinking on this some more, I want to be sure we are actually testing plumber and not the filters or serializers.
I've added a test file below to compare how fast the core of plumber is, with and without filters and serializers. Routes that end in default test using filters and a serializer. The testing routes test the core plumber response time.
Show that there is a difference in the routes...
...at least 50% faster if filters and serializers are not used.
I'll make a PR soon copying the style of https://github.com/the-benchmarker/web-frameworks/pull/3255