diff -Nru r-cran-bench-1.1.2/debian/changelog r-cran-bench-1.1.3/debian/changelog --- r-cran-bench-1.1.2/debian/changelog 2021-12-05 20:08:27.000000000 +0000 +++ r-cran-bench-1.1.3/debian/changelog 2023-06-21 07:24:57.000000000 +0000 @@ -1,3 +1,13 @@ +r-cran-bench (1.1.3-1) unstable; urgency=medium + + * Team upload. + * New upstream version + * Standards-Version: 4.6.2 (routine-update) + * dh-update-R to update Build-Depends (routine-update) + * Testsuite: autopkgtest-pkg-r (routine-update) + + -- Andreas Tille Wed, 21 Jun 2023 09:24:57 +0200 + r-cran-bench (1.1.2-1) unstable; urgency=medium * Team Upload. diff -Nru r-cran-bench-1.1.2/debian/control r-cran-bench-1.1.3/debian/control --- r-cran-bench-1.1.2/debian/control 2021-12-05 20:07:48.000000000 +0000 +++ r-cran-bench-1.1.3/debian/control 2023-06-21 07:24:57.000000000 +0000 @@ -2,16 +2,17 @@ Maintainer: Debian R Packages Maintainers Uploaders: Michael R. Crusoe Section: gnu-r +Testsuite: autopkgtest-pkg-r Priority: optional Build-Depends: debhelper-compat (= 13), dh-r, r-base-dev, - r-cran-glue, - r-cran-pillar, + r-cran-glue (>= 1.6.2), + r-cran-pillar (>= 1.9.0), r-cran-profmem, r-cran-rlang, - r-cran-tibble (>= 3.0.1) -Standards-Version: 4.6.0 + r-cran-tibble (>= 3.2.1) +Standards-Version: 4.6.2 Vcs-Browser: https://salsa.debian.org/r-pkg-team/r-cran-bench Vcs-Git: https://salsa.debian.org/r-pkg-team/r-cran-bench.git Homepage: https://cran.r-project.org/package=bench diff -Nru r-cran-bench-1.1.2/DESCRIPTION r-cran-bench-1.1.3/DESCRIPTION --- r-cran-bench-1.1.2/DESCRIPTION 2021-11-30 07:50:13.000000000 +0000 +++ r-cran-bench-1.1.3/DESCRIPTION 2023-05-04 16:50:02.000000000 +0000 @@ -1,30 +1,33 @@ Package: bench Title: High Precision Timing of R Expressions -Version: 1.1.2 +Version: 1.1.3 Authors@R: c( person("Jim", "Hester", role = "aut"), - person("Davis", "Vaughan", , "davis@rstudio.com", role = c("aut", "cre")), + person("Davis", "Vaughan", , "davis@posit.co", role = c("aut", "cre")), person("Drew", "Schmidt", role = "ctb", - comment = "read_proc_file implementation") + comment = "read_proc_file implementation"), + person("Posit Software, PBC", role = c("cph", "fnd")) ) Description: Tools to accurately benchmark and analyze execution times for R expressions. License: MIT + file LICENSE URL: https://bench.r-lib.org/, https://github.com/r-lib/bench BugReports: https://github.com/r-lib/bench/issues -Depends: R (>= 3.1) -Imports: glue, methods, pillar, profmem, rlang (>= 0.2.0), stats, - tibble (>= 3.0.1), utils +Depends: R (>= 3.5.0) +Imports: glue (>= 1.6.2), methods, pillar (>= 1.9.0), profmem (>= + 0.6.0), rlang (>= 0.2.0), stats, tibble (>= 3.2.1), utils Suggests: covr, dplyr, forcats, ggbeeswarm, ggplot2, ggridges, - jsonlite, mockery, parallel, scales, testthat, tidyr (>= - 0.8.1), vctrs, withr + parallel, scales, testthat (>= 3.1.8), tidyr (>= 0.8.1), vctrs, + withr +Config/testthat/edition: 3 Encoding: UTF-8 -RoxygenNote: 7.1.2 +RoxygenNote: 7.2.3 NeedsCompilation: yes -Packaged: 2021-11-29 16:12:02 UTC; jhester +Packaged: 2023-05-04 13:38:24 UTC; davis Author: Jim Hester [aut], Davis Vaughan [aut, cre], - Drew Schmidt [ctb] (read_proc_file implementation) -Maintainer: Davis Vaughan + Drew Schmidt [ctb] (read_proc_file implementation), + Posit Software, PBC [cph, fnd] +Maintainer: Davis Vaughan Repository: CRAN -Date/Publication: 2021-11-30 07:50:13 UTC +Date/Publication: 2023-05-04 16:50:02 UTC diff -Nru r-cran-bench-1.1.2/LICENSE r-cran-bench-1.1.3/LICENSE --- r-cran-bench-1.1.2/LICENSE 2021-11-23 21:29:54.000000000 +0000 +++ r-cran-bench-1.1.3/LICENSE 2023-05-03 14:05:25.000000000 +0000 @@ -1,2 +1,2 @@ -YEAR: 2020 +YEAR: 2023 COPYRIGHT HOLDER: bench authors diff -Nru r-cran-bench-1.1.2/man/autoplot.bench_mark.Rd r-cran-bench-1.1.3/man/autoplot.bench_mark.Rd --- r-cran-bench-1.1.2/man/autoplot.bench_mark.Rd 2020-07-06 14:05:32.000000000 +0000 +++ r-cran-bench-1.1.3/man/autoplot.bench_mark.Rd 2023-05-03 14:05:25.000000000 +0000 @@ -54,7 +54,7 @@ dat[which(dat$x > 500), ], subset(dat, x > 500)) -if (require(ggplot2) && require(tidyr)) { +if (require(ggplot2) && require(tidyr) && require(ggbeeswarm)) { # Beeswarm plot autoplot(res) diff -Nru r-cran-bench-1.1.2/man/bench-package.Rd r-cran-bench-1.1.3/man/bench-package.Rd --- r-cran-bench-1.1.2/man/bench-package.Rd 2021-11-29 15:40:30.000000000 +0000 +++ r-cran-bench-1.1.3/man/bench-package.Rd 2023-05-03 14:05:25.000000000 +0000 @@ -33,7 +33,7 @@ } \author{ -\strong{Maintainer}: Davis Vaughan \email{davis@rstudio.com} +\strong{Maintainer}: Davis Vaughan \email{davis@posit.co} Authors: \itemize{ @@ -43,6 +43,7 @@ Other contributors: \itemize{ \item Drew Schmidt (read_proc_file implementation) [contributor] + \item Posit Software, PBC [copyright holder, funder] } } diff -Nru r-cran-bench-1.1.2/man/bench_process_memory.Rd r-cran-bench-1.1.3/man/bench_process_memory.Rd --- r-cran-bench-1.1.2/man/bench_process_memory.Rd 2021-11-29 15:39:01.000000000 +0000 +++ r-cran-bench-1.1.3/man/bench_process_memory.Rd 2023-05-04 12:55:35.000000000 +0000 @@ -15,8 +15,8 @@ The OS APIs used are as follows \subsection{Windows}{ \itemize{ -\item \href{https://docs.microsoft.com/en-us/windows/win32/api/psapi/ns-psapi-process_memory_counters}{PROCESS_MEMORY_COUNTERS.WorkingSetSize} -\item \href{https://docs.microsoft.com/en-us/windows/win32/api/psapi/ns-psapi-process_memory_counters}{PROCESS_MEMORY_COUNTERS.PeakWorkingSetSize} +\item \href{https://learn.microsoft.com/en-us/windows/win32/api/psapi/ns-psapi-process_memory_counters}{PROCESS_MEMORY_COUNTERS.WorkingSetSize} +\item \href{https://learn.microsoft.com/en-us/windows/win32/api/psapi/ns-psapi-process_memory_counters}{PROCESS_MEMORY_COUNTERS.PeakWorkingSetSize} } } @@ -31,8 +31,6 @@ \itemize{ \item \href{https://man7.org/linux/man-pages/man5/proc.5.html}{/proc/pid/status VmSize} \item \href{https://man7.org/linux/man-pages/man5/proc.5.html}{/proc/pid/status VmPeak} -and on Windows -\href{https://docs.microsoft.com/en-us/windows/win32/api/psapi/ns-psapi-process_memory_counters}{PROCESS_MEMORY_COUNTERS.PeakWorkingSetSize} } } } Binary files /tmp/tmppwuppf9x/z01BSrk4l9/r-cran-bench-1.1.2/man/figures/README-autoplot-1.png and /tmp/tmppwuppf9x/_q9Y6WEDRl/r-cran-bench-1.1.3/man/figures/README-autoplot-1.png differ Binary files /tmp/tmppwuppf9x/z01BSrk4l9/r-cran-bench-1.1.2/man/figures/README-custom-plot-1.png and /tmp/tmppwuppf9x/_q9Y6WEDRl/r-cran-bench-1.1.3/man/figures/README-custom-plot-1.png differ Binary files /tmp/tmppwuppf9x/z01BSrk4l9/r-cran-bench-1.1.2/man/figures/README-pressure-1.png and /tmp/tmppwuppf9x/_q9Y6WEDRl/r-cran-bench-1.1.3/man/figures/README-pressure-1.png differ diff -Nru r-cran-bench-1.1.2/man/knit_print.bench_mark.Rd r-cran-bench-1.1.3/man/knit_print.bench_mark.Rd --- r-cran-bench-1.1.2/man/knit_print.bench_mark.Rd 2020-02-11 14:18:51.000000000 +0000 +++ r-cran-bench-1.1.3/man/knit_print.bench_mark.Rd 2023-05-03 14:50:17.000000000 +0000 @@ -2,7 +2,7 @@ % Please edit documentation in R/mark.R \name{knit_print.bench_mark} \alias{knit_print.bench_mark} -\title{Custom printing function for bench_mark objects in knitr documents} +\title{Custom printing function for \code{bench_mark} objects in knitr documents} \usage{ knit_print.bench_mark(x, ..., options) } @@ -13,19 +13,23 @@ except two optional arguments \code{options} and \code{inline}; see the references below.} -\item{options}{A list of knitr chunk options set in the currently evaluated chunk.} +\item{options}{A list of knitr chunk options set in the currently evaluated +chunk.} } \description{ -By default data columns ('result', 'memory', 'time', 'gc') are omitted when -printing in knitr. If you would like to include these columns set the knitr -chunk option 'bench.all_columns = TRUE'. +By default, data columns (\code{result}, \code{memory}, \code{time}, \code{gc}) are omitted when +printing in knitr. If you would like to include these columns, set the knitr +chunk option \code{bench.all_columns = TRUE}. } \details{ You can set \code{bench.all_columns = TRUE} to show all columns of the bench mark -object.\preformatted{```\{r bench.all_columns = TRUE\} +object. + +\if{html}{\out{
}}\preformatted{```\{r, bench.all_columns = TRUE\} bench::mark( subset(mtcars, cyl == 3), - mtcars[mtcars$cyl == 3, ]) + mtcars[mtcars$cyl == 3, ] +) ``` -} +}\if{html}{\out{
}} } diff -Nru r-cran-bench-1.1.2/man/mark.Rd r-cran-bench-1.1.3/man/mark.Rd --- r-cran-bench-1.1.2/man/mark.Rd 2020-02-11 14:18:51.000000000 +0000 +++ r-cran-bench-1.1.3/man/mark.Rd 2023-05-03 14:13:21.000000000 +0000 @@ -41,8 +41,8 @@ pair of results to determine consistency.} \item{memory}{If \code{TRUE} (the default when R is compiled with memory -profiling), track memory allocations using. If \code{FALSE} disable memory -tracking.} +profiling), track memory allocations using \code{\link[utils:Rprofmem]{utils::Rprofmem()}}. If \code{FALSE} +disable memory tracking.} \item{filter_gc}{If \code{TRUE} remove iterations that contained at least one garbage collection before summarizing. If \code{TRUE} but an expression had diff -Nru r-cran-bench-1.1.2/MD5 r-cran-bench-1.1.3/MD5 --- r-cran-bench-1.1.2/MD5 2021-11-30 07:50:13.000000000 +0000 +++ r-cran-bench-1.1.3/MD5 2023-05-04 16:50:02.000000000 +0000 @@ -1,59 +1,61 @@ -2be19b38ed96231960dca40e48f5a651 *DESCRIPTION -37b3d1fa5ae9f97de7ac49d6af126d1d *LICENSE -038a94ec64f0685546ff6c03bf130771 *NAMESPACE -664306ba2ddc051b00a7bbe83387121b *NEWS.md -7be32a97ba64d1a18348854e6205b2bd *R/autoplot.R -ea7992cf90bb4cb5f36512829f62c1d5 *R/bench-package.R -8d1adc5463ea824fcccd2441d3fb17da *R/bench_process_memory.R +ddf35e99a4f639f1c76492fa9f623527 *DESCRIPTION +01cb7550abd5f5cf564d96da079ed7c1 *LICENSE +78b3992a2ed4432c432e127ff54c2d3d *NAMESPACE +d0c424b75f71c7abf800ced2c2ee9f07 *NEWS.md +ea1433ebe9323f10ad39558685666fc5 *R/autoplot.R +1a5454237e1734bffcf9f30acbbc192e *R/bench-package.R +cd9f2a6098ebc356020778349ae318e2 *R/bench_process_memory.R 1ee5f554612a36963a0ee6d2a65578cf *R/bench_time.R -ba194d26b0344d7492987996d1dc2c49 *R/bytes.R -09e662a6a328315c2607353b70703426 *R/expression.R +645544e1f986afb493949378fb5a4d5d *R/bytes.R +ab15a232cc07a944504adcfca4381f35 *R/expression.R 77e68ec28bbdde8f4bedaff981f6309f *R/hires_time.R +366ed49f7ae3591e236f9916aca1aa3d *R/import-standalone-s3-register.R 51a94b8001e3229a6950b42643c9feb2 *R/load.R -b9651048df9c3462f24817c7a06287c0 *R/mark.R -e2dc4876f5d1fcc1181ed46736da219f *R/press.R -baf1716216309e457a706920e387fb90 *R/time.R -0e4a58c2627bc70eb652525cae2ab66f *R/utils.R +860a30db3b622aaaa9526a473802fca8 *R/mark.R +32601a0ce0db2276c3c2f68049472d60 *R/press.R +167429ef93d6d3e12009e775f85ad4f7 *R/time.R +2409f0e916296f52686b93e26b069f46 *R/utils.R e1bbe29b95d0d57ed776b04826483acc *R/workout.R -7bb570528f275ab419ce0108456b63d8 *R/zzz.R -83380b1d3607784c0e6e3b9aed3a7150 *README.md +e204e52ccf14d3d121ea192680fcaf2a *R/zzz.R +87fadeaebc514738350d66bfdad719cc *README.md 1fe3413a86a0c4c2906e7165a90f50c6 *inst/examples/exprs.R 7caab55fd54d91cb18f632e305601d2a *man/as_bench_mark.Rd 30db463e739be59bd8ab5f860369ba18 *man/as_bench_time.Rd -4691c983194c470647c4b23310bb6e04 *man/autoplot.bench_mark.Rd -553a1eb20c03497b65aba21ae05b62e8 *man/bench-package.Rd +becf294614b6c8f909fa4efcd67bfa6d *man/autoplot.bench_mark.Rd +860fe02b8996a0796f2214b85a31f5af *man/bench-package.Rd e00da89923ce7cb5acfefc0aebbee819 *man/bench_bytes.Rd b00acbed01dc7a2c5fa82573a44f2b5d *man/bench_bytes_trans.Rd 2de6749ef7f5d6c1c68734bbb4d81aae *man/bench_load_average.Rd c18918dfaaa633fea6f00f17b5b21053 *man/bench_memory.Rd -eb5d32051b5c89408d76e90a81057f78 *man/bench_process_memory.Rd +7caad6578f5a4540ea5df724ed7dace4 *man/bench_process_memory.Rd 2e18e19606c9c1c1d5ea5ccba1642005 *man/bench_time.Rd a8137bcbacc4e74c922c29ed701499cc *man/bench_time_trans.Rd -b1a915af152c37bc96447534a48e94bf *man/figures/README-autoplot-1.png -14a106c98d808ee78b32ab21e6a2b699 *man/figures/README-custom-plot-1.png -e8ffa8ffebc73b316e9cf2e1d1245939 *man/figures/README-pressure-1.png +2ffa360ca5ef05477039e9eae9f318e0 *man/figures/README-autoplot-1.png +8643c59be2df01f7082be204b3ef7afb *man/figures/README-custom-plot-1.png fdac20c9c4139609fea0f9e64981956c *man/hires_time.Rd -b089ea2b51a2a9046b8c9e2a57a894ad *man/knit_print.bench_mark.Rd -f760a978aed96e0d1e9d5e0dba3fa758 *man/mark.Rd +a73a679ddea597dac7a172d843483a23 *man/knit_print.bench_mark.Rd +26eefb1ea43c365ef599f42eaeabbdef *man/mark.Rd caa5b8ea96c93c2db3c412122018741f *man/press.Rd 082d65d3d1143fa4b2cf8dbdf685301a *man/scale_bench_expr.Rd 2a72e434c9dc761c8c989a2a06c1ecba *man/scale_bench_time.Rd 3eb90d05fc5b5e05b18edf3756ad9174 *man/summary.bench_mark.Rd f025b1dfc97f6c46ad65f26e0f7f05b4 *man/workout.Rd aca489119fcc0bf9b67ba6d99e10f7f2 *src/Makevars.win -ea08595d2801262b68e67e830f629ef7 *src/load.c -fe7486b920834d6e38e0928fa213f19f *src/mark.c -b38c6c7a859e6b2cc4db88256ace6785 *src/nanotime.c -2a199e99c4051ee86d32d73561f58d22 *src/nanotime.h -bea51994f8a5ce146b207a8ee1339bd8 *src/os.h -6516b3bad34f1af7733fe49e2334d6a8 *src/process_memory.c -d8db634775f53a1a9e93912e01b798db *tests/testthat.R +23950326a3c36819758c500d11cb753f *src/load.c +f2c720fbda25db33899c8ee386978707 *src/mark.c +da4293a8454c4cf6d04e6085cb030a71 *src/nanotime.c +a4ddcbf152c7cc443c7fc4d419b7ba02 *src/nanotime.h +3292c9d23affdceeb30aca948ae0609c *src/os.h +e9c07bac16328c31e7dfbeb94920d2e4 *src/process_memory.c +6fac3fba3b03a971f611b6de40e077ab *tests/testthat.R +e2fdb651b601e9ac62412338db079d61 *tests/testthat/_snaps/mark.md +7914e7f96609801fee4cde25abe1dd09 *tests/testthat/_snaps/press.md a0a974655bfb7e72da63bce70ae07d96 *tests/testthat/test-bench_process_memory.R -11868a9ec8d55f835eeb90752c85d5e3 *tests/testthat/test-bench_time.R -a56252f27fa9e1a6962845380a098e7c *tests/testthat/test-bytes.R +42443448baee8c2082f6c764d80f44bd *tests/testthat/test-bench_time.R +f79988b1bdecf29c85a43229052e97b9 *tests/testthat/test-bytes.R 0650fd0059de42081c725b3678ab6223 *tests/testthat/test-expression.R -0650ba599bd979b856d197b87eeb791a *tests/testthat/test-hires_time.R -8af2acddab88e9df85b0a54b48f73c60 *tests/testthat/test-mark.R -c3ea6e9b56c6f9681754d8581fb47089 *tests/testthat/test-press.R -471464fac8c966eb4addd79450802e19 *tests/testthat/test-time.R +4a6a82facc351c8d376ae071da009c26 *tests/testthat/test-hires_time.R +6ce10f27c5c0b63162351a13c9d1ded5 *tests/testthat/test-mark.R +ef3d501480dd1a9add39cabf1e004773 *tests/testthat/test-press.R +c298d65c0be2f98828ec89088a14b8ae *tests/testthat/test-time.R a75b5a6a77f0e3121feaa6fc195964a8 *tests/testthat/test-workout.R diff -Nru r-cran-bench-1.1.2/NAMESPACE r-cran-bench-1.1.3/NAMESPACE --- r-cran-bench-1.1.2/NAMESPACE 2021-11-29 16:11:26.000000000 +0000 +++ r-cran-bench-1.1.3/NAMESPACE 2023-05-04 12:44:50.000000000 +0000 @@ -26,6 +26,9 @@ S3method(mean,bench_time) S3method(min,bench_bytes) S3method(min,bench_time) +S3method(pillar_shaft,bench_bytes) +S3method(pillar_shaft,bench_expr) +S3method(pillar_shaft,bench_time) S3method(plot,bench_mark) S3method(print,bench_bytes) S3method(print,bench_expr) @@ -34,6 +37,9 @@ S3method(sum,bench_bytes) S3method(sum,bench_time) S3method(summary,bench_mark) +S3method(type_sum,bench_bytes) +S3method(type_sum,bench_expr) +S3method(type_sum,bench_time) export(as_bench_bytes) export(as_bench_mark) export(as_bench_time) @@ -59,4 +65,6 @@ export(workout) export(workout_expressions) importFrom(methods,setOldClass) +importFrom(pillar,pillar_shaft) +importFrom(pillar,type_sum) useDynLib(bench, .registration = TRUE) diff -Nru r-cran-bench-1.1.2/NEWS.md r-cran-bench-1.1.3/NEWS.md --- r-cran-bench-1.1.2/NEWS.md 2021-11-29 16:11:38.000000000 +0000 +++ r-cran-bench-1.1.3/NEWS.md 2023-05-04 13:04:43.000000000 +0000 @@ -1,3 +1,21 @@ +# bench 1.1.3 + +* Long unnamed `bench_expr` expressions are now truncated correctly when used as + columns of a tibble (#94). + +* `bench_mark` tibbles now respect the knitr paged df option (#103). + +* Fixed an issue where macOS specific C code paths were accidentally being used + on GNU Hurd (#118). + +* Fixed `-Wstrict-prototypes` warnings, as requested by CRAN (#124). + +* R >=3.5.0 is now required, which is aligned with tidyverse standards. + +* bench now uses testthat 3e (#129). + +* bench no longer Suggests mockery. + # bench 1.1.2 * Davis Vaughan is now the maintainer. diff -Nru r-cran-bench-1.1.2/R/autoplot.R r-cran-bench-1.1.3/R/autoplot.R --- r-cran-bench-1.1.2/R/autoplot.R 2020-05-20 12:43:06.000000000 +0000 +++ r-cran-bench-1.1.3/R/autoplot.R 2023-05-03 14:05:25.000000000 +0000 @@ -27,7 +27,7 @@ #' dat[which(dat$x > 500), ], #' subset(dat, x > 500)) #' -#' if (require(ggplot2) && require(tidyr)) { +#' if (require(ggplot2) && require(tidyr) && require(ggbeeswarm)) { #' #' # Beeswarm plot #' autoplot(res) diff -Nru r-cran-bench-1.1.2/R/bench-package.R r-cran-bench-1.1.3/R/bench-package.R --- r-cran-bench-1.1.2/R/bench-package.R 2020-02-11 14:18:51.000000000 +0000 +++ r-cran-bench-1.1.3/R/bench-package.R 2023-05-04 12:40:04.000000000 +0000 @@ -1,3 +1,10 @@ +## usethis namespace: start +#' @importFrom methods setOldClass +#' @importFrom pillar pillar_shaft +#' @importFrom pillar type_sum +## usethis namespace: end +NULL + #' @keywords internal #' @inherit summary.bench_mark examples "_PACKAGE" diff -Nru r-cran-bench-1.1.2/R/bench_process_memory.R r-cran-bench-1.1.3/R/bench_process_memory.R --- r-cran-bench-1.1.2/R/bench_process_memory.R 2021-11-29 15:39:01.000000000 +0000 +++ r-cran-bench-1.1.3/R/bench_process_memory.R 2023-05-04 12:55:22.000000000 +0000 @@ -7,16 +7,14 @@ #' The OS APIs used are as follows #' #' ## Windows -#' - [PROCESS_MEMORY_COUNTERS.WorkingSetSize](https://docs.microsoft.com/en-us/windows/win32/api/psapi/ns-psapi-process_memory_counters) -#' - [PROCESS_MEMORY_COUNTERS.PeakWorkingSetSize](https://docs.microsoft.com/en-us/windows/win32/api/psapi/ns-psapi-process_memory_counters) +#' - [PROCESS_MEMORY_COUNTERS.WorkingSetSize](https://learn.microsoft.com/en-us/windows/win32/api/psapi/ns-psapi-process_memory_counters) +#' - [PROCESS_MEMORY_COUNTERS.PeakWorkingSetSize](https://learn.microsoft.com/en-us/windows/win32/api/psapi/ns-psapi-process_memory_counters) #' ## macOS #' - [task_info(TASK_BASIC_INFO)](https://developer.apple.com/documentation/kernel/1537934-task_info?language=occ) #' - [rusage.ru_maxrss](https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/getrusage.2.html) #' ## linux #' - [/proc/pid/status VmSize](https://man7.org/linux/man-pages/man5/proc.5.html) #' - [/proc/pid/status VmPeak](https://man7.org/linux/man-pages/man5/proc.5.html) -#' and on Windows -#' [PROCESS_MEMORY_COUNTERS.PeakWorkingSetSize](https://docs.microsoft.com/en-us/windows/win32/api/psapi/ns-psapi-process_memory_counters) #' @export bench_process_memory <- function() { stats::setNames( diff -Nru r-cran-bench-1.1.2/R/bytes.R r-cran-bench-1.1.3/R/bytes.R --- r-cran-bench-1.1.2/R/bytes.R 2020-02-11 14:18:51.000000000 +0000 +++ r-cran-bench-1.1.3/R/bytes.R 2023-05-04 12:41:15.000000000 +0000 @@ -37,7 +37,6 @@ structure(x, class = c("bench_bytes", "numeric")) } -#' @importFrom methods setOldClass setOldClass(c("bench_bytes", "numeric"), numeric()) #' @export @@ -149,10 +148,12 @@ NextMethod(.Generic) } +#' @export pillar_shaft.bench_bytes <- function(x, ...) { pillar::new_pillar_shaft_simple(format.bench_bytes(x), align = "right", ...) } +#' @export type_sum.bench_bytes <- function(x) { "bch:byt" } diff -Nru r-cran-bench-1.1.2/R/expression.R r-cran-bench-1.1.3/R/expression.R --- r-cran-bench-1.1.2/R/expression.R 2020-07-06 14:05:32.000000000 +0000 +++ r-cran-bench-1.1.3/R/expression.R 2023-05-04 12:41:19.000000000 +0000 @@ -23,6 +23,7 @@ NextMethod() } +#' @export type_sum.bench_expr <- function(x) { "bch:expr" } @@ -46,8 +47,12 @@ new_bench_expr(x$x, x$desc) } +#' @export pillar_shaft.bench_expr <- function(x, ...) { - pillar::new_pillar_shaft_simple(format.bench_expr(x), align = "left", ...) + # We format bench expressions exactly like character vectors. This ensures + # they are truncated as needed, which is useful for long unnamed expressions + # (#94). This is the same logic as `pillar:::pillar_shaft.factor()`. + pillar_shaft(as.character(x), ...) } scale_type.bench_expr <- function(x) { diff -Nru r-cran-bench-1.1.2/R/import-standalone-s3-register.R r-cran-bench-1.1.3/R/import-standalone-s3-register.R --- r-cran-bench-1.1.2/R/import-standalone-s3-register.R 1970-01-01 00:00:00.000000000 +0000 +++ r-cran-bench-1.1.3/R/import-standalone-s3-register.R 2023-05-04 12:49:29.000000000 +0000 @@ -0,0 +1,187 @@ +# Standalone file: do not edit by hand +# Source: +# ---------------------------------------------------------------------- +# +# --- +# repo: r-lib/rlang +# file: standalone-s3-register.R +# last-updated: 2022-08-29 +# license: https://unlicense.org +# --- +# +# nocov start + +#' Register a method for a suggested dependency +#' +#' Generally, the recommended way to register an S3 method is to use the +#' `S3Method()` namespace directive (often generated automatically by the +#' `@export` roxygen2 tag). However, this technique requires that the generic +#' be in an imported package, and sometimes you want to suggest a package, +#' and only provide a method when that package is loaded. `s3_register()` +#' can be called from your package's `.onLoad()` to dynamically register +#' a method only if the generic's package is loaded. +#' +#' For R 3.5.0 and later, `s3_register()` is also useful when demonstrating +#' class creation in a vignette, since method lookup no longer always involves +#' the lexical scope. For R 3.6.0 and later, you can achieve a similar effect +#' by using "delayed method registration", i.e. placing the following in your +#' `NAMESPACE` file: +#' +#' ``` +#' if (getRversion() >= "3.6.0") { +#' S3method(package::generic, class) +#' } +#' ``` +#' +#' @section Usage in other packages: +#' To avoid taking a dependency on vctrs, you copy the source of +#' [`s3_register()`](https://github.com/r-lib/rlang/blob/main/R/standalone-s3-register.R) +#' into your own package. It is licensed under the permissive +#' [unlicense](https://choosealicense.com/licenses/unlicense/) to make it +#' crystal clear that we're happy for you to do this. There's no need to include +#' the license or even credit us when using this function. +#' +#' @param generic Name of the generic in the form `"pkg::generic"`. +#' @param class Name of the class +#' @param method Optionally, the implementation of the method. By default, +#' this will be found by looking for a function called `generic.class` +#' in the package environment. +#' @examples +#' # A typical use case is to dynamically register tibble/pillar methods +#' # for your class. That way you avoid creating a hard dependency on packages +#' # that are not essential, while still providing finer control over +#' # printing when they are used. +#' +#' .onLoad <- function(...) { +#' s3_register("pillar::pillar_shaft", "vctrs_vctr") +#' s3_register("tibble::type_sum", "vctrs_vctr") +#' } +#' @keywords internal +#' @noRd +s3_register <- function(generic, class, method = NULL) { + stopifnot(is.character(generic), length(generic) == 1) + stopifnot(is.character(class), length(class) == 1) + + pieces <- strsplit(generic, "::")[[1]] + stopifnot(length(pieces) == 2) + package <- pieces[[1]] + generic <- pieces[[2]] + + caller <- parent.frame() + + get_method_env <- function() { + top <- topenv(caller) + if (isNamespace(top)) { + asNamespace(environmentName(top)) + } else { + caller + } + } + get_method <- function(method) { + if (is.null(method)) { + get(paste0(generic, ".", class), envir = get_method_env()) + } else { + method + } + } + + register <- function(...) { + envir <- asNamespace(package) + + # Refresh the method each time, it might have been updated by + # `devtools::load_all()` + method_fn <- get_method(method) + stopifnot(is.function(method_fn)) + + + # Only register if generic can be accessed + if (exists(generic, envir)) { + registerS3method(generic, class, method_fn, envir = envir) + } else if (identical(Sys.getenv("NOT_CRAN"), "true")) { + warn <- .rlang_s3_register_compat("warn") + + warn(c( + sprintf( + "Can't find generic `%s` in package %s to register S3 method.", + generic, + package + ), + "i" = "This message is only shown to developers using devtools.", + "i" = sprintf("Do you need to update %s to the latest version?", package) + )) + } + } + + # Always register hook in case package is later unloaded & reloaded + setHook(packageEvent(package, "onLoad"), function(...) { + register() + }) + + # For compatibility with R < 4.1.0 where base isn't locked + is_sealed <- function(pkg) { + identical(pkg, "base") || environmentIsLocked(asNamespace(pkg)) + } + + # Avoid registration failures during loading (pkgload or regular). + # Check that environment is locked because the registering package + # might be a dependency of the package that exports the generic. In + # that case, the exports (and the generic) might not be populated + # yet (#1225). + if (isNamespaceLoaded(package) && is_sealed(package)) { + register() + } + + invisible() +} + +.rlang_s3_register_compat <- function(fn, try_rlang = TRUE) { + # Compats that behave the same independently of rlang's presence + out <- switch( + fn, + is_installed = return(function(pkg) requireNamespace(pkg, quietly = TRUE)) + ) + + # Only use rlang if it is fully loaded (#1482) + if (try_rlang && + requireNamespace("rlang", quietly = TRUE) && + environmentIsLocked(asNamespace("rlang"))) { + switch( + fn, + is_interactive = return(rlang::is_interactive) + ) + + # Make sure rlang knows about "x" and "i" bullets + if (utils::packageVersion("rlang") >= "0.4.2") { + switch( + fn, + abort = return(rlang::abort), + warn = return((rlang::warn)), + inform = return(rlang::inform) + ) + } + } + + # Fall back to base compats + + is_interactive_compat <- function() { + opt <- getOption("rlang_interactive") + if (!is.null(opt)) { + opt + } else { + interactive() + } + } + + format_msg <- function(x) paste(x, collapse = "\n") + switch( + fn, + is_interactive = return(is_interactive_compat), + abort = return(function(msg) stop(format_msg(msg), call. = FALSE)), + warn = return(function(msg) warning(format_msg(msg), call. = FALSE)), + inform = return(function(msg) message(format_msg(msg))) + ) + + stop(sprintf("Internal error in rlang shims: Unknown function `%s()`.", fn)) +} + +# nocov end diff -Nru r-cran-bench-1.1.2/R/mark.R r-cran-bench-1.1.3/R/mark.R --- r-cran-bench-1.1.2/R/mark.R 2021-11-29 16:11:26.000000000 +0000 +++ r-cran-bench-1.1.3/R/mark.R 2023-05-04 12:27:43.000000000 +0000 @@ -23,8 +23,8 @@ #' stored. If `check` is a function that function will be called with each #' pair of results to determine consistency. #' @param memory If `TRUE` (the default when R is compiled with memory -#' profiling), track memory allocations using. If `FALSE` disable memory -#' tracking. +#' profiling), track memory allocations using [utils::Rprofmem()]. If `FALSE` +#' disable memory tracking. #' @param env The environment which to evaluate the expressions #' @inheritParams summary.bench_mark #' @inherit summary.bench_mark return @@ -119,7 +119,7 @@ error <- NULL gc_msg <- with_gcinfo({ tryCatch(error = function(e) { e$call <- NULL; error <<- e}, - res <- .Call(mark_, exprs[[i]], env, min_time, as.integer(min_iterations), as.integer(max_iterations)) + res <- .Call(mark_, exprs[[i]], env, min_time, as.integer(min_iterations), as.integer(max_iterations), TRUE) ) }) if (!is.null(error)) { @@ -301,34 +301,38 @@ #nocov start -#' Custom printing function for bench_mark objects in knitr documents +#' Custom printing function for `bench_mark` objects in knitr documents +#' +#' By default, data columns (`result`, `memory`, `time`, `gc`) are omitted when +#' printing in knitr. If you would like to include these columns, set the knitr +#' chunk option `bench.all_columns = TRUE`. #' -#' By default data columns ('result', 'memory', 'time', 'gc') are omitted when -#' printing in knitr. If you would like to include these columns set the knitr -#' chunk option 'bench.all_columns = TRUE'. -#' @param options A list of knitr chunk options set in the currently evaluated chunk. -#' @inheritParams knitr::knit_print #' @details #' You can set `bench.all_columns = TRUE` to show all columns of the bench mark #' object. #' -#' ```{r bench.all_columns = TRUE} +#' ```{r, bench.all_columns = TRUE} #' bench::mark( #' subset(mtcars, cyl == 3), -#' mtcars[mtcars$cyl == 3, ]) +#' mtcars[mtcars$cyl == 3, ] +#' ) #' ``` +#' +#' @inheritParams knitr::knit_print +#' +#' @param options A list of knitr chunk options set in the currently evaluated +#' chunk. knit_print.bench_mark <- function(x, ..., options) { - if (isTRUE(options$bench.all_columns)) { - print(x) - } else { - print(x[!colnames(x) %in% data_cols]) + if (!isTRUE(options$bench.all_columns)) { + x <- x[!colnames(x) %in% data_cols] } + NextMethod() } #nocov end parse_gc <- function(x) { - # \x1E is Record Separator  + # \x1E is Record Separator x <- strsplit(paste0(x, collapse = ""), "\x1E")[[1]] tibble::as_tibble(.Call(parse_gc_, x)) } diff -Nru r-cran-bench-1.1.2/R/press.R r-cran-bench-1.1.3/R/press.R --- r-cran-bench-1.1.2/R/press.R 2021-11-23 21:29:54.000000000 +0000 +++ r-cran-bench-1.1.3/R/press.R 2023-05-03 15:28:42.000000000 +0000 @@ -16,7 +16,7 @@ #' @param ... If named, parameters to define, if unnamed the expression to run. #' Only one unnamed expression is permitted. #' @param .grid A pre-built grid of values to use, typically a [data.frame] or -#' [tibble]. This is useful if you only want to benchmark a subset of all +#' [tibble]. This is useful if you only want to benchmark a subset of all #' possible combinations. #' @export #' @examples @@ -64,18 +64,26 @@ parameters <- expand.grid(lapply(args[!unnamed], rlang::eval_tidy), stringsAsFactors = FALSE) } - status <- format(tibble::as_tibble(parameters), n = Inf) - message(glue::glue(" - Running with: - {status[[2]]}")) + quiet <- bench_press_quiet() + + if (!quiet) { + status <- format(tibble::as_tibble(parameters), n = Inf) + message(glue::glue("Running with:\n{status[[2]]}")) + } + eval_one <- function(row) { e <- rlang::new_data_mask(new.env(parent = emptyenv())) + for (col in seq_along(parameters)) { var <- names(parameters)[[col]] value <- parameters[row, col] assign(var, value, envir = e) } - message(status[[row + 3L]]) + + if (!quiet) { + message(status[[row + 3L]]) + } + rlang::eval_tidy(args[[which(unnamed)]], data = e) } @@ -90,3 +98,13 @@ parameters <- parameters[rep(seq_len(nrow(parameters)), each = rows[[1]]), , drop = FALSE] bench_mark(tibble::as_tibble(cbind(res[1], parameters, res[-1]))) } + +bench_press_quiet <- function() { + # Internal option to silence `press()` during testing + isTRUE(getOption("bench.press_quiet", default = FALSE)) +} + +local_press_quiet <- function(frame = rlang::caller_env()) { + rlang::local_options(bench.press_quiet = TRUE, .frame = frame) +} + diff -Nru r-cran-bench-1.1.2/R/time.R r-cran-bench-1.1.3/R/time.R --- r-cran-bench-1.1.2/R/time.R 2020-02-14 13:39:20.000000000 +0000 +++ r-cran-bench-1.1.3/R/time.R 2023-05-04 12:41:22.000000000 +0000 @@ -189,10 +189,12 @@ new_bench_time(NextMethod(.Generic)) } +#' @export pillar_shaft.bench_time <- function(x, ...) { pillar::new_pillar_shaft_simple(format.bench_time(x), align = "right", ...) } +#' @export type_sum.bench_time <- function(x) { "bch:tm" } diff -Nru r-cran-bench-1.1.2/R/utils.R r-cran-bench-1.1.3/R/utils.R --- r-cran-bench-1.1.2/R/utils.R 2020-07-06 14:05:32.000000000 +0000 +++ r-cran-bench-1.1.3/R/utils.R 2023-05-04 12:27:43.000000000 +0000 @@ -38,8 +38,6 @@ names } -utils::globalVariables("_rval_") - with_gcinfo <- function(expr) { tf <- tempfile() con <- file(tf, "wb") @@ -84,10 +82,6 @@ get("is_latex_output", asNamespace("knitr"))() } -collapse <- function(x, sep) { - paste0(x, collapse = sep) -} - lengths <- function(x, use.names = TRUE) { viapply(x, length, USE.NAMES = use.names) } @@ -97,32 +91,6 @@ utils::packageVersion("tidyr") > "0.8.99" } -# Read lines as UTF-8 -read_lines <- function (path, n = -1L, encoding = "UTF-8") { - base::readLines(path, n = n, encoding = encoding, warn = FALSE) -} - -has_description <- function(path) { - file.exists(file.path(path, "DESCRIPTION")) -} - -find_package_root <- function(path) { - path <- normalizePath(path, mustWork = FALSE) - - while(!has_description(path)) { - path <- dirname(path) - if (is_root(path)) { - return(NULL) - } - } - - sub("[/\\]$", "", path) -} - -is_root <- function(path) { - identical(path, dirname(path)) -} - dots <- function(...) { dots <- as.list(substitute(...())) diff -Nru r-cran-bench-1.1.2/R/zzz.R r-cran-bench-1.1.3/R/zzz.R --- r-cran-bench-1.1.2/R/zzz.R 2020-07-06 14:05:32.000000000 +0000 +++ r-cran-bench-1.1.3/R/zzz.R 2023-05-04 12:51:11.000000000 +0000 @@ -1,50 +1,17 @@ #nocov start .onLoad <- function(...) { - register_s3_method("tidyr", "unnest", "bench_mark") - register_s3_method("dplyr", "filter", "bench_mark") - register_s3_method("dplyr", "group_by", "bench_mark") - register_s3_method("ggplot2", "autoplot", "bench_mark") + s3_register("tidyr::unnest", "bench_mark") + s3_register("dplyr::filter", "bench_mark") + s3_register("dplyr::group_by", "bench_mark") + s3_register("ggplot2::autoplot", "bench_mark") + + s3_register("ggplot2::scale_type", "bench_expr") + s3_register("ggplot2::scale_type", "bench_time") + s3_register("ggplot2::scale_type", "bench_bytes") - register_s3_method("pillar", "pillar_shaft", "bench_expr") - register_s3_method("pillar", "type_sum", "bench_expr") - register_s3_method("ggplot2", "scale_type", "bench_expr") + s3_register("knitr::knit_print", "bench_mark") - register_s3_method("pillar", "pillar_shaft", "bench_time") - register_s3_method("pillar", "type_sum", "bench_time") - register_s3_method("ggplot2", "scale_type", "bench_time") - - register_s3_method("pillar", "pillar_shaft", "bench_bytes") - register_s3_method("pillar", "type_sum", "bench_bytes") - register_s3_method("ggplot2", "scale_type", "bench_bytes") - - register_s3_method("knitr", "knit_print", "bench_mark") - - register_s3_method("vctrs", "vec_proxy", "bench_expr") - register_s3_method("vctrs", "vec_restore", "bench_expr") + s3_register("vctrs::vec_proxy", "bench_expr") + s3_register("vctrs::vec_restore", "bench_expr") } - -register_s3_method <- function(pkg, generic, class, fun = NULL) { - stopifnot(is.character(pkg), length(pkg) == 1) - stopifnot(is.character(generic), length(generic) == 1) - stopifnot(is.character(class), length(class) == 1) - - if (is.null(fun)) { - fun <- get(paste0(generic, ".", class), envir = parent.frame()) - } else { - stopifnot(is.function(fun)) - } - - if (pkg %in% loadedNamespaces()) { - registerS3method(generic, class, fun, envir = asNamespace(pkg)) - } - - # Always register hook in case package is later unloaded & reloaded - setHook( - packageEvent(pkg, "onLoad"), - function(...) { - registerS3method(generic, class, fun, envir = asNamespace(pkg)) - } - ) -} - #nocov end diff -Nru r-cran-bench-1.1.2/README.md r-cran-bench-1.1.3/README.md --- r-cran-bench-1.1.2/README.md 2021-11-29 16:11:26.000000000 +0000 +++ r-cran-bench-1.1.3/README.md 2023-05-04 12:59:53.000000000 +0000 @@ -5,12 +5,12 @@ -[![R build -status](https://github.com/r-lib/bench/workflows/R-CMD-check/badge.svg)](https://github.com/r-lib/bench) -[![Coverage -status](https://codecov.io/gh/r-lib/bench/branch/master/graph/badge.svg)](https://codecov.io/github/r-lib/bench?branch=master) [![CRAN status](https://www.r-pkg.org/badges/version/bench)](https://cran.r-project.org/package=bench) +[![R-CMD-check](https://github.com/r-lib/bench/actions/workflows/R-CMD-check.yaml/badge.svg)](https://github.com/r-lib/bench/actions/workflows/R-CMD-check.yaml) +[![Codecov test +coverage](https://codecov.io/gh/r-lib/bench/branch/main/graph/badge.svg)](https://app.codecov.io/gh/r-lib/bench?branch=main) + The goal of bench is to benchmark code, tracking execution time, memory @@ -29,8 +29,8 @@ [GitHub](https://github.com/) with: ``` r -# install.packages("remotes") -remotes::install_github("r-lib/bench") +# install.packages("pak") +pak::pak("r-lib/bench") ``` ## Features @@ -38,29 +38,29 @@ `bench::mark()` is used to benchmark one or a series of expressions, we feel it has a number of advantages over [alternatives](#alternatives). -- Always uses the highest precision APIs available for each operating - system (often nanoseconds). -- Tracks memory allocations for each expression. -- Tracks the number and type of R garbage collections per expression - iteration. -- Verifies equality of expression results by default, to avoid - accidentally benchmarking inequivalent code. -- Has `bench::press()`, which allows you to easily perform and combine - benchmarks across a large grid of values. -- Uses adaptive stopping by default, running each expression for a set - amount of time rather than for a specific number of iterations. -- Expressions are run in batches and summary statistics are calculated - after filtering out iterations with garbage collections. This allows - you to isolate the performance and effects of garbage collection on - running time (for more details see [Neal - 2014](https://radfordneal.wordpress.com/2014/02/02/inaccurate-results-from-microbenchmark/)). +- Always uses the highest precision APIs available for each operating + system (often nanoseconds). +- Tracks memory allocations for each expression. +- Tracks the number and type of R garbage collections per expression + iteration. +- Verifies equality of expression results by default, to avoid + accidentally benchmarking inequivalent code. +- Has `bench::press()`, which allows you to easily perform and combine + benchmarks across a large grid of values. +- Uses adaptive stopping by default, running each expression for a set + amount of time rather than for a specific number of iterations. +- Expressions are run in batches and summary statistics are calculated + after filtering out iterations with garbage collections. This allows + you to isolate the performance and effects of garbage collection on + running time (for more details see [Neal + 2014](https://radfordneal.wordpress.com/2014/02/02/inaccurate-results-from-microbenchmark/)). The times and memory usage are returned as custom objects which have human readable formatting for display (e.g. `104ns`) and comparisons -(e.g. `x$mem_alloc > "10MB"`). +(e.g. `x$mem_alloc > "10MB"`). There is also full support for plotting with -[ggplot2](http://ggplot2.tidyverse.org/) including custom scales and +[ggplot2](https://ggplot2.tidyverse.org/) including custom scales and formatting. ## Usage @@ -73,7 +73,11 @@ ``` r library(bench) set.seed(42) -dat <- data.frame(x = runif(10000, 1, 1000), y=runif(10000, 1, 1000)) + +dat <- data.frame( + x = runif(10000, 1, 1000), + y = runif(10000, 1, 1000) +) ``` `bench::mark()` will throw an error if the results are not equivalent, @@ -83,7 +87,8 @@ bench::mark( dat[dat$x > 500, ], dat[which(dat$x > 499), ], - subset(dat, x > 500)) + subset(dat, x > 500) +) #> Error: Each result must equal the first result: #> `dat[dat$x > 500, ]` does not equal `dat[which(dat$x > 499), ]` ``` @@ -94,14 +99,15 @@ bnch <- bench::mark( dat[dat$x > 500, ], dat[which(dat$x > 500), ], - subset(dat, x > 500)) + subset(dat, x > 500) +) bnch #> # A tibble: 3 × 6 #> expression min median `itr/sec` mem_alloc `gc/sec` #> -#> 1 dat[dat$x > 500, ] 258µs 383µs 2543. 377KB 17.1 -#> 2 dat[which(dat$x > 500), ] 204µs 260µs 3803. 260KB 17.7 -#> 3 subset(dat, x > 500) 332µs 426µs 2318. 510KB 20.7 +#> 1 dat[dat$x > 500, ] 277µs 383µs 2485. 377KB 16.3 +#> 2 dat[which(dat$x > 500), ] 203µs 276µs 3635. 260KB 16.9 +#> 3 subset(dat, x > 500) 361µs 487µs 1981. 510KB 16.8 ``` By default the summary uses absolute measures, however relative results @@ -113,9 +119,9 @@ #> # A tibble: 3 × 6 #> expression min median `itr/sec` mem_alloc `gc/sec` #> -#> 1 dat[dat$x > 500, ] 1.26 1.47 1.10 1.45 1 -#> 2 dat[which(dat$x > 500), ] 1 1 1.64 1 1.03 -#> 3 subset(dat, x > 500) 1.63 1.64 1 1.96 1.21 +#> 1 dat[dat$x > 500, ] 1.36 1.39 1.25 1.45 1 +#> 2 dat[which(dat$x > 500), ] 1 1 1.84 1 1.03 +#> 3 subset(dat, x > 500) 1.78 1.77 1 1.96 1.03 ``` ### `bench::press()` @@ -131,9 +137,9 @@ set.seed(42) create_df <- function(rows, cols) { - as.data.frame(setNames( - replicate(cols, runif(rows, 1, 100), simplify = FALSE), - rep_len(c("x", letters), cols))) + out <- replicate(cols, runif(rows, 1, 100), simplify = FALSE) + out <- setNames(out, rep_len(c("x", letters), cols)) + as.data.frame(out) } results <- bench::press( @@ -155,22 +161,23 @@ #> 2 10000 2 #> 3 1000 10 #> 4 10000 10 + results #> # A tibble: 12 × 8 #> expression rows cols min median `itr/sec` mem_alloc `gc/sec` #> -#> 1 bracket 1000 2 25.3µs 33µs 29008. 15.84KB 11.6 -#> 2 which 1000 2 25.5µs 32.5µs 29813. 7.91KB 8.95 -#> 3 subset 1000 2 45.8µs 56.7µs 17164. 27.7KB 8.66 -#> 4 bracket 10000 2 45.6µs 60µs 16286. 156.46KB 56.1 -#> 5 which 10000 2 40.4µs 42.9µs 20583. 78.23KB 31.7 -#> 6 subset 10000 2 94.6µs 117.5µs 8158. 273.79KB 49.1 -#> 7 bracket 1000 10 64.4µs 77µs 12601. 47.52KB 12.8 -#> 8 which 1000 10 58.9µs 63.3µs 14338. 7.91KB 12.4 -#> 9 subset 1000 10 85.1µs 104.7µs 8755. 59.38KB 10.7 -#> 10 bracket 10000 10 128.9µs 144.6µs 6752. 469.4KB 70.3 -#> 11 which 10000 10 89.8µs 97.3µs 9699. 78.23KB 14.8 -#> 12 subset 10000 10 189.5µs 232.9µs 4180. 586.73KB 56.8 +#> 1 bracket 1000 2 27µs 34µs 27964. 15.84KB 19.6 +#> 2 which 1000 2 25.7µs 33.4µs 29553. 7.91KB 17.7 +#> 3 subset 1000 2 45.9µs 58.2µs 16793. 27.7KB 17.1 +#> 4 bracket 10000 2 64.1µs 70.8µs 13447. 156.46KB 40.5 +#> 5 which 10000 2 46.7µs 54.7µs 17586. 78.23KB 23.3 +#> 6 subset 10000 2 116.2µs 132.1µs 7228. 273.79KB 40.9 +#> 7 bracket 1000 10 77.2µs 85.4µs 11335. 47.52KB 19.9 +#> 8 which 1000 10 67.8µs 75.2µs 13073. 7.91KB 23.2 +#> 9 subset 1000 10 84.7µs 107.5µs 9281. 59.38KB 18.8 +#> 10 bracket 10000 10 130.2µs 169.1µs 5799. 469.4KB 52.2 +#> 11 which 10000 10 75.1µs 96µs 10187. 78.23KB 17.4 +#> 12 subset 10000 10 222.7µs 253µs 3810. 586.73KB 43.3 ``` ## Plotting @@ -191,6 +198,20 @@ You can also produce fully custom plots by un-nesting the results and working with the data directly. +``` r +library(tidyverse) + +results %>% + unnest(c(time, gc)) %>% + filter(gc == "none") %>% + mutate(expression = as.character(expression)) %>% + ggplot(aes(x = mem_alloc, y = time, color = expression)) + + geom_point() + + scale_color_bench_expr(scales::brewer_pal(type = "qual", palette = 3)) +``` + + + ## `system_time()` **bench** also includes `system_time()`, a higher precision alternative @@ -198,17 +219,23 @@ [system.time()](https://www.rdocumentation.org/packages/base/versions/3.5.0/topics/system.time). ``` r -bench::system_time({ i <- 1; while(i < 1e7) i <- i + 1 }) +bench::system_time({ + i <- 1 + while(i < 1e7) { + i <- i + 1 + } +}) #> process real -#> 2.37s 2.37s +#> 222ms 223ms + bench::system_time(Sys.sleep(.5)) #> process real -#> 91µs 500ms +#> 88µs 502ms ``` ## Alternatives -- [rbenchmark](https://cran.r-project.org/package=rbenchmark) -- [microbenchmark](https://cran.r-project.org/package=microbenchmark) -- [tictoc](https://cran.r-project.org/package=tictoc) -- [system.time()](https://www.rdocumentation.org/packages/base/versions/3.5.0/topics/system.time) +- [rbenchmark](https://cran.r-project.org/package=rbenchmark) +- [microbenchmark](https://cran.r-project.org/package=microbenchmark) +- [tictoc](https://cran.r-project.org/package=tictoc) +- [system.time()](https://www.rdocumentation.org/packages/base/versions/3.5.0/topics/system.time) diff -Nru r-cran-bench-1.1.2/src/load.c r-cran-bench-1.1.3/src/load.c --- r-cran-bench-1.1.2/src/load.c 2020-03-05 19:40:40.000000000 +0000 +++ r-cran-bench-1.1.3/src/load.c 2023-05-03 14:05:25.000000000 +0000 @@ -8,7 +8,7 @@ #include #endif -SEXP bench_load_average_() { +SEXP bench_load_average_(void) { SEXP out = PROTECT(Rf_allocVector(REALSXP, 3)); REAL(out)[0] = NA_REAL; diff -Nru r-cran-bench-1.1.2/src/mark.c r-cran-bench-1.1.3/src/mark.c --- r-cran-bench-1.1.2/src/mark.c 2021-11-23 21:29:53.000000000 +0000 +++ r-cran-bench-1.1.3/src/mark.c 2023-05-03 16:30:45.000000000 +0000 @@ -23,10 +23,11 @@ return overhead; } -SEXP mark_(SEXP expr, SEXP env, SEXP min_time, SEXP min_itr, SEXP max_itr) { +SEXP mark_(SEXP expr, SEXP env, SEXP min_time, SEXP min_itr, SEXP max_itr, SEXP gcinfo) { R_xlen_t min_itr_ = INTEGER(min_itr)[0]; R_xlen_t max_itr_ = INTEGER(max_itr)[0]; double min_time_ = REAL(min_time)[0]; + Rboolean gcinfo_ = LOGICAL(gcinfo)[0]; SEXP out = PROTECT(Rf_allocVector(REALSXP, max_itr_)); @@ -39,8 +40,12 @@ long double elapsed = expr_elapsed_time(expr, env); - // 1E is record separator  - REprintf("\x1E"); + if (gcinfo_) { + // We don't emit the separator during low level testing of `mark_()` + // 1E is record separator + REprintf("\x1E"); + } + REAL(out)[i] = elapsed - overhead; total+=elapsed; @@ -72,7 +77,7 @@ return out; } -SEXP hires_time_() { +SEXP hires_time_(void) { double time = real_time(); SEXP out = PROTECT(Rf_allocVector(REALSXP, 1)); REAL(out)[0] = time; @@ -115,11 +120,11 @@ return out; } -extern SEXP bench_process_memory_(); -extern SEXP bench_load_average_(); +extern SEXP bench_process_memory_(void); +extern SEXP bench_load_average_(void); static const R_CallMethodDef CallEntries[] = { - {"mark_", (DL_FUNC) &mark_, 5}, + {"mark_", (DL_FUNC) &mark_, 6}, {"system_time_", (DL_FUNC) &system_time_, 2}, {"bench_process_memory_", (DL_FUNC) &bench_process_memory_, 0}, {"bench_load_average_", (DL_FUNC) &bench_load_average_, 0}, diff -Nru r-cran-bench-1.1.2/src/nanotime.c r-cran-bench-1.1.3/src/nanotime.c --- r-cran-bench-1.1.2/src/nanotime.c 2020-02-11 14:18:51.000000000 +0000 +++ r-cran-bench-1.1.3/src/nanotime.c 2023-05-03 14:05:25.000000000 +0000 @@ -1,8 +1,9 @@ #include "nanotime.h" +#include "os.h" -#ifdef __WIN32 +#if OS_WINDOWS #include -#elif defined(__MACH__) +#elif OS_MACOS #include #include #include @@ -15,8 +16,8 @@ #endif -#if defined(_WIN32) || defined(_WIN64) -long double real_time() { +#if OS_WINDOWS +long double real_time(void) { // https://msdn.microsoft.com/en-us/library/windows/desktop/ms644904(v=vs.85).aspx static LARGE_INTEGER frequency; frequency.QuadPart = 0; @@ -31,8 +32,8 @@ } return (long double) count.QuadPart / frequency.QuadPart; } -#elif defined(__MACH__) -long double real_time() { +#elif OS_MACOS +long double real_time(void) { // https://developer.apple.com/library/content/qa/qa1398/_index.html //static mach_timebase_info_data_t info; @@ -50,15 +51,15 @@ uint64_t nanos = time * ratio; return (long double)nanos / NSEC_PER_SEC; } -#elif defined(__sun) -long double real_time() { +#elif OS_SOLARIS +long double real_time(void) { hrtime_t time = gethrtime(); // The man page doesn't mention any error return values return (long double)time / NSEC_PER_SEC; } #else -long double real_time() { +long double real_time(void) { struct timespec ts; if (clock_gettime(CLOCK_REALTIME, &ts) != 0) { Rf_error("clock_gettime(CLOCK_REALTIME, ...) failed"); @@ -68,8 +69,8 @@ } #endif -long double process_cpu_time() { -#if defined(_WIN32) || defined(_WIN64) +long double process_cpu_time(void) { +#if OS_WINDOWS HANDLE proc = GetCurrentProcess(); FILETIME creation_time; FILETIME exit_time; @@ -86,18 +87,21 @@ user.HighPart = user_time.dwHighDateTime; user.LowPart = user_time.dwLowDateTime; return (((long double)kernel.QuadPart + (long double)user.QuadPart) * 1e-7); -#elif defined(__sun) +#elif OS_SOLARIS hrtime_t time = gethrvtime(); // The man page doesn't mention any error return values return (long double)time / NSEC_PER_SEC; #elif defined(CLOCK_PROCESS_CPUTIME_ID) + // Modern macOS and Linux struct timespec ts; if (clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &ts) != 0) { Rf_error("clock_gettime(CLOCK_PROCESS_CPUTIME_ID, ...) failed"); } return ts.tv_sec + (long double)ts.tv_nsec / NSEC_PER_SEC; #else + // macOS before 10.12 didn't define `CLOCK_PROCESS_CPUTIME_ID` + // https://github.com/r-lib/bench/commit/cfd4e2392f980e29d833f4df42a43ea2ba131aaf struct rusage ru; if (getrusage(RUSAGE_SELF, &ru) != 0) { Rf_error("getrusage(RUSAGE_SELF, ...) failed"); diff -Nru r-cran-bench-1.1.2/src/nanotime.h r-cran-bench-1.1.3/src/nanotime.h --- r-cran-bench-1.1.2/src/nanotime.h 2020-02-11 14:18:51.000000000 +0000 +++ r-cran-bench-1.1.3/src/nanotime.h 2023-05-03 14:05:25.000000000 +0000 @@ -3,8 +3,8 @@ #include "Rinternals.h" -long double real_time(); -long double process_cpu_time(); +long double real_time(void); +long double process_cpu_time(void); long double expr_elapsed_time(SEXP expr, SEXP env); #endif diff -Nru r-cran-bench-1.1.2/src/os.h r-cran-bench-1.1.3/src/os.h --- r-cran-bench-1.1.2/src/os.h 2020-02-11 14:18:51.000000000 +0000 +++ r-cran-bench-1.1.3/src/os.h 2023-05-03 14:05:25.000000000 +0000 @@ -19,4 +19,10 @@ #define OS_LINUX 0 #endif +#ifdef __sun +#define OS_SOLARIS 1 +#else +#define OS_SOLARIS 0 +#endif + #endif diff -Nru r-cran-bench-1.1.2/src/process_memory.c r-cran-bench-1.1.3/src/process_memory.c --- r-cran-bench-1.1.2/src/process_memory.c 2020-02-11 14:18:51.000000000 +0000 +++ r-cran-bench-1.1.3/src/process_memory.c 2023-05-03 14:05:25.000000000 +0000 @@ -76,7 +76,7 @@ } #endif -SEXP bench_process_memory_() { +SEXP bench_process_memory_(void) { SEXP out = PROTECT(Rf_allocVector(REALSXP, 2)); REAL(out)[0] = NA_REAL; diff -Nru r-cran-bench-1.1.2/tests/testthat/_snaps/mark.md r-cran-bench-1.1.3/tests/testthat/_snaps/mark.md --- r-cran-bench-1.1.2/tests/testthat/_snaps/mark.md 1970-01-01 00:00:00.000000000 +0000 +++ r-cran-bench-1.1.3/tests/testthat/_snaps/mark.md 2023-05-04 12:45:10.000000000 +0000 @@ -0,0 +1,28 @@ +# mark: Can errors with the deparsed expressions + + Code + mark(1, 1, 3, max_iterations = 10) + Condition + Error: + ! Each result must equal the first result: + `1` does not equal `3` + +# mark: Works when calls are different lengths + + Code + mark(if (TRUE) 2, if (TRUE) 1 else 3) + Condition + Error: + ! Each result must equal the first result: + `if (TRUE) 2` does not equal `if (TRUE) 1 else 3` + +# mark: truncates long expressions when printing (#94) + + Code + out + Output + # A tibble: 1 x 2 + expression result + + 1 aaaaaaaaaaaaaaaaaaaa~ + diff -Nru r-cran-bench-1.1.2/tests/testthat/_snaps/press.md r-cran-bench-1.1.3/tests/testthat/_snaps/press.md --- r-cran-bench-1.1.2/tests/testthat/_snaps/press.md 1970-01-01 00:00:00.000000000 +0000 +++ r-cran-bench-1.1.3/tests/testthat/_snaps/press.md 2023-05-04 12:45:11.000000000 +0000 @@ -0,0 +1,17 @@ +# press: Outputs status message before evaluating each parameter + + Code + res <- press(x = 1, mark(rep(1, x), max_iterations = 10)) + Message + Running with: + x + 1 1 + +--- + + Code + messages + Output + [1] "Running with:\n x\n" "1 1\n" + [3] "2 2\n" "3 3\n" + diff -Nru r-cran-bench-1.1.2/tests/testthat/test-bench_time.R r-cran-bench-1.1.3/tests/testthat/test-bench_time.R --- r-cran-bench-1.1.2/tests/testthat/test-bench_time.R 2020-02-11 14:18:51.000000000 +0000 +++ r-cran-bench-1.1.3/tests/testthat/test-bench_time.R 2023-05-03 14:05:25.000000000 +0000 @@ -8,13 +8,13 @@ it("returns times that are reasonable, system and real time are relatively close for process bound expressions", { epsilon <- abs(res[[1]] - res[[2]]) - expect_true((epsilon / res[[1]]) < 1) + expect_true((epsilon / res[[1]]) < 5) }) it("returns times that are reasonable, system and real time are far apart for non-process bound expressions", { res <- bench_time(Sys.sleep(.5)) epsilon <- abs(res[[1]] - res[[2]]) - expect_true((epsilon / res[[1]]) > 100) + expect_true((epsilon / res[[1]]) > 20) }) }) diff -Nru r-cran-bench-1.1.2/tests/testthat/test-bytes.R r-cran-bench-1.1.3/tests/testthat/test-bytes.R --- r-cran-bench-1.1.2/tests/testthat/test-bytes.R 2020-02-11 14:18:51.000000000 +0000 +++ r-cran-bench-1.1.3/tests/testthat/test-bytes.R 2023-05-03 14:05:25.000000000 +0000 @@ -1,5 +1,3 @@ -context("test-bytes.R") - describe("as_bench_bytes", { it("accepts numeric input unchanged", { expect_equal(unclass(as_bench_bytes(123L)), 123L) diff -Nru r-cran-bench-1.1.2/tests/testthat/test-hires_time.R r-cran-bench-1.1.3/tests/testthat/test-hires_time.R --- r-cran-bench-1.1.2/tests/testthat/test-hires_time.R 2020-02-11 14:18:51.000000000 +0000 +++ r-cran-bench-1.1.3/tests/testthat/test-hires_time.R 2023-05-03 14:05:25.000000000 +0000 @@ -7,7 +7,7 @@ start <- hires_time() Sys.sleep(.1) end <- hires_time() - expect_is(start, "numeric") + expect_type(start, "double") expect_true(end > start) }) }) diff -Nru r-cran-bench-1.1.2/tests/testthat/test-mark.R r-cran-bench-1.1.3/tests/testthat/test-mark.R --- r-cran-bench-1.1.2/tests/testthat/test-mark.R 2020-02-11 14:18:51.000000000 +0000 +++ r-cran-bench-1.1.3/tests/testthat/test-mark.R 2023-05-03 16:30:45.000000000 +0000 @@ -1,24 +1,22 @@ -context("test-mark.R") - describe("mark_", { it("If min_time is Inf, runs for max_iterations", { - res <- .Call(mark_, quote(1), new.env(), Inf, as.integer(0), as.integer(10)) + res <- .Call(mark_, quote(1), new.env(), Inf, as.integer(0), as.integer(10), FALSE) expect_equal(length(res), 10) - res <- .Call(mark_, quote(1), new.env(), Inf, as.integer(0), as.integer(20)) + res <- .Call(mark_, quote(1), new.env(), Inf, as.integer(0), as.integer(20), FALSE) expect_equal(length(res), 20) }) it("If min_time is 0, runs for min_iterations", { - res <- .Call(mark_, quote(1), new.env(), 0, as.integer(1), as.integer(10)) + res <- .Call(mark_, quote(1), new.env(), 0, as.integer(1), as.integer(10), FALSE) expect_equal(length(res), 1) - res <- .Call(mark_, quote(1), new.env(), 0, as.integer(5), as.integer(10)) + res <- .Call(mark_, quote(1), new.env(), 0, as.integer(5), as.integer(10), FALSE) expect_equal(length(res), 5) }) it("If min_time is 0, runs for min_iterations", { - res <- .Call(mark_, quote({i <- 1; while(i < 10000) i <- i + 1}), new.env(), .1, as.integer(1), as.integer(1000)) + res <- .Call(mark_, quote({i <- 1; while(i < 10000) i <- i + 1}), new.env(), .1, as.integer(1), as.integer(1000), FALSE) expect_gte(length(res), 1) expect_lte(length(res), 1000) @@ -26,7 +24,7 @@ it("Evaluates code in the environment", { e <- new.env(parent = baseenv()) - res <- .Call(mark_, quote({a <- 42}), e, Inf, as.integer(1), as.integer(1)) + res <- .Call(mark_, quote({a <- 42}), e, Inf, as.integer(1), as.integer(1), FALSE) expect_equal(e[["a"]], 42) }) }) @@ -35,7 +33,7 @@ it("Uses all.equal to check results by default", { res <- mark(1 + 1, 1L + 1L, check = TRUE, iterations = 1) - expect_is(res$result, "list") + expect_type(res$result, "list") expect_true(all.equal(res$result[[1]], res$result[[2]])) }) it("Can use other functions to check results like identical to check results", { @@ -51,7 +49,7 @@ # Function that always returns true res <- mark(1 + 1, 1 + 2, check = function(x, y) TRUE, iterations = 1) - expect_is(res$result, "list") + expect_type(res$result, "list") expect_equal(res$result[[1]], 2) expect_equal(res$result[[2]], 3) }) @@ -63,15 +61,13 @@ expect_equal(length(res$memory), 2) - expect_is(res$memory[[1]], "Rprofmem") + expect_s3_class(res$memory[[1]], "Rprofmem") expect_equal(ncol(res$memory[[1]]), 3) expect_gte(nrow(res$memory[[1]]), 0) }) it("works without capabilities('profmem')", { - mockery::stub(mark, "capabilities", FALSE) - - res <- mark(1, 2, check = FALSE, iterations = 1) + res <- mark(1, 2, check = FALSE, iterations = 1, memory = FALSE) expect_equal(res$memory, vector("list", 2)) expect_equal(res$mem_alloc, as_bench_bytes(c(NA, NA))) @@ -81,30 +77,31 @@ expect_equal(res$result, list(NULL)) }) it("Can errors with the deparsed expressions", { - expect_error(msg = "`1` does not equal `3`", - mark(1, 1, 3, max_iterations = 10)) + expect_snapshot(error = TRUE, { + mark(1, 1, 3, max_iterations = 10) + }) }) it("Works when calls are different lengths", { - expect_error(msg = "does not equal", + expect_snapshot(error = TRUE, { # Here the first call deparses to length 2, the second to length 4 mark(if (TRUE) 2, if (TRUE) 1 else 3) - ) + }) }) it("works with memory = FALSE", { res <- mark(1, memory = FALSE) - expect_is(res, "bench_mark") + expect_s3_class(res, "bench_mark") expect_equal(res$memory, vector("list", 1)) expect_equal(res$mem_alloc, as_bench_bytes(NA)) }) it("works with check = FALSE", { res <- mark(1, check = FALSE) - expect_is(res, "bench_mark") + expect_s3_class(res, "bench_mark") expect_equal(res$result, list(NULL)) }) it("works with memory = FALSE and check = FALSE", { res <- mark(1, memory = FALSE, check = FALSE) - expect_is(res, "bench_mark") + expect_s3_class(res, "bench_mark") expect_equal(res$memory, list(NULL)) expect_equal(res$mem_alloc, as_bench_bytes(NA)) }) @@ -129,6 +126,21 @@ 2 + 2, ) }) + it("truncates long expressions when printing (#94)", { + local_reproducible_output(width = 30) + + name <- paste0(rep("a", 100), collapse = "") + exprs <- list(as.name(name)) + + assign(name, 1, envir = environment()) + + out <- mark(exprs = exprs) + + # Only snapshot static columns + out <- out[c("expression", "result")] + + expect_snapshot(out) + }) }) describe("summary.bench_mark", { diff -Nru r-cran-bench-1.1.2/tests/testthat/test-press.R r-cran-bench-1.1.3/tests/testthat/test-press.R --- r-cran-bench-1.1.2/tests/testthat/test-press.R 2020-02-11 14:18:51.000000000 +0000 +++ r-cran-bench-1.1.3/tests/testthat/test-press.R 2023-05-03 15:38:31.000000000 +0000 @@ -1,8 +1,8 @@ -context("test-press.R") - describe("press", { it("Adds parameters to output", { + local_press_quiet() + res <- press( x = 1, mark(1, max_iterations = 10) @@ -19,34 +19,39 @@ }) it("Outputs status message before evaluating each parameter", { - expect_message(regexp = "Running with:\n.*x", - res <- press( - x = 1, - mark(rep(1, x), max_iterations = 10) - ) - ) + expect_snapshot({ + res <- press(x = 1, mark(rep(1, x), max_iterations = 10)) + }) expect_equal(colnames(res), c("expression", "x", summary_cols, data_cols)) expect_equal(nrow(res), 1) - msgs <- character() - withCallingHandlers(message = function(e) msgs <<- append(msgs, conditionMessage(e)), - res2 <- press( + messages <- character() + withCallingHandlers( + res <- press( x = 1:3, mark(rep(1, x), max_iterations = 10) - ) + ), + message = function(cnd) { + messages <<- append(messages, conditionMessage(cnd)) + if (!is.null(findRestart("muffleMessage"))) { + invokeRestart("muffleMessage") + } + } ) - expect_true(grepl("Running with:\n.*x\n.*1\n.*2\n.*3\n", paste(msgs, collapse = ""))) - - expect_equal(colnames(res2), c("expression", "x", summary_cols, data_cols)) - expect_equal(nrow(res2), 3) + expect_snapshot(messages) + expect_equal(colnames(res), c("expression", "x", summary_cols, data_cols)) + expect_equal(nrow(res), 3) }) it("expands the grid if has named parameters", { + local_press_quiet() + res <- press( x = c(1, 2), y = c(1, 3), mark(list(x, y), max_iterations = 10) ) + expect_equal(res$x, c(1, 2, 1, 2)) expect_equal(res$y, c(1, 1, 3, 3)) expect_equal(res$result[[1]], list(1, 1)) @@ -56,10 +61,13 @@ }) it("takes values as-is if given in .grid", { + local_press_quiet() + res <- press( .grid = data.frame(x = c(1, 2), y = c(1,3)), mark(list(x, y), max_iterations = 10) ) + expect_equal(res$x, c(1, 2)) expect_equal(res$y, c(1, 3)) expect_equal(res$result[[1]], list(1, 1)) @@ -67,13 +75,17 @@ }) it("runs `setup` with the parameters evaluated", { + local_press_quiet() + x <- 1 res <- press( y = 2, { x <- y mark(x) - }) + } + ) + expect_equal(res$result[[1]], 2) }) }) diff -Nru r-cran-bench-1.1.2/tests/testthat/test-time.R r-cran-bench-1.1.3/tests/testthat/test-time.R --- r-cran-bench-1.1.2/tests/testthat/test-time.R 2020-02-14 13:39:20.000000000 +0000 +++ r-cran-bench-1.1.3/tests/testthat/test-time.R 2023-05-03 14:05:25.000000000 +0000 @@ -1,5 +1,3 @@ -context("test-time.R") - describe("as_bench_time", { it("accepts numeric input unchanged", { expect_equal(unclass(as_bench_time(123L)), 123L) diff -Nru r-cran-bench-1.1.2/tests/testthat.R r-cran-bench-1.1.3/tests/testthat.R --- r-cran-bench-1.1.2/tests/testthat.R 2020-02-11 14:18:51.000000000 +0000 +++ r-cran-bench-1.1.3/tests/testthat.R 2023-05-03 14:05:25.000000000 +0000 @@ -1,3 +1,11 @@ +# This file is part of the standard setup for testthat. +# It is recommended that you do not modify it. +# +# Where should you do additional test configuration? +# Learn more about the roles of various files in: +# * https://r-pkgs.org/tests.html +# * https://testthat.r-lib.org/reference/test_package.html#special-files + library(testthat) library(bench)