Skip to content

Commit 0c59ba9

Browse files
committed
refactor: make perf test tolerances configurable via profile
1 parent bd18856 commit 0c59ba9

5 files changed

Lines changed: 72 additions & 9 deletions

File tree

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
# Performance Tests
2+
3+
Performance tests measure the throughput (operations per second) of server-side functions and compare against baseline rates stored in profile CSV files.
4+
5+
## How it works
6+
7+
Each performance test:
8+
9+
1. Runs a function in a loop for 30 seconds and calculates the current rate (ops/sec).
10+
2. Looks up the baseline rate for that test in the active profile CSV.
11+
3. If no entry exists, a new one is saved to the profile using the current rate and the profile-level default tolerances.
12+
4. Asserts that the current rate falls within `[baseline * lower_tolerance, baseline * upper_tolerance]`.
13+
14+
## Profiles
15+
16+
Profile CSVs live in `perf_files/` and contain columns:
17+
18+
| Column | Description |
19+
|--------|-------------|
20+
| `refer_name` | Unique test identifier (e.g. `meanDS::perf::numeric::0`) |
21+
| `rate` | Baseline ops/sec |
22+
| `lower_tolerance` | Multiplier for the lower bound (e.g. `0.5` = 50% of baseline) |
23+
| `upper_tolerance` | Multiplier for the upper bound (e.g. `2.0` = 200% of baseline) |
24+
25+
Available profiles:
26+
27+
- `default_perf_profile.csv` -- default baseline
28+
- `performance_refactor_profile.csv` -- for local development; no effective upper limit
29+
- `azure-pipeline.csv`, `circleci.csv` -- CI-specific baselines
30+
31+
## Switching profiles
32+
33+
Set `.perf.reference.filename` in `setup.R` before sourcing `perf_rate.R`:
34+
35+
```r
36+
.perf.reference.filename <- "perf_files/performance_refactor_profile.csv"
37+
source("perf_tests/perf_rate.R")
38+
```
39+
40+
If not set, `perf_rate.R` defaults to `perf_files/default_perf_profile.csv`.
41+
42+
## Self-populating entries
43+
44+
When a test has no entry in the active profile, `perf.reference.save()` creates one using the current measured rate and the profile-level tolerances (`perf.profile.tolerance.lower/upper()`), which are read from the first row of the profile CSV. This means new tests automatically inherit the tolerance policy of whichever profile is active.
45+
46+
## Skipping
47+
48+
Performance tests are skipped on CRAN (`skip_on_cran()`) and CI (`skip_on_ci()`) by default, since results are hardware-dependent.

tests/testthat/perf_tests/perf_rate.R

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,28 @@
88
# along with this program. If not, see <http://www.gnu.org/licenses/>.
99
#-------------------------------------------------------------------------------
1010

11-
.perf.reference.filename <- 'perf_files/default_perf_profile.csv'
11+
.perf.reference.filename <- getOption("perf.profile", "perf_files/default_perf_profile.csv")
1212

1313
.perf.reference <- NULL
1414

1515
.load.pref <- function() {
1616
.perf.reference <<- read.csv(.perf.reference.filename, header = TRUE, sep = ",")
1717
}
1818

19+
perf.profile.tolerance.lower <- function() {
20+
if (is.null(.perf.reference))
21+
.load.pref()
22+
23+
return(as.numeric(.perf.reference$lower_tolerance[1]))
24+
}
25+
26+
perf.profile.tolerance.upper <- function() {
27+
if (is.null(.perf.reference))
28+
.load.pref()
29+
30+
return(as.numeric(.perf.reference$upper_tolerance[1]))
31+
}
32+
1933
perf.reference.save <- function(perf.ref.name, rate, tolerance.lower, tolerance.upper) {
2034
if (is.null(.perf.reference))
2135
load.pref()

tests/testthat/setup.R

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ library(lme4)
2121
source("disclosure/set_disclosure_settings.R")
2222
source("random/set_random_seed_settings.R")
2323

24+
options(perf.profile = "perf_files/performance_refactor_profile.csv")
2425
source("perf_tests/perf_rate.R")
2526

2627
# context("setup - done")

tests/testthat/test-perf-meanDS.R

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -45,8 +45,8 @@ test_that("numeric meanDS - performance", {
4545
.current.rate <- .count / (difftime(.current.time, .start.time, units = "secs")[[1]])
4646
.reference.rate <- perf.reference.rate("meanDS::perf::numeric::0")
4747
if (any(length(.reference.rate) == 0) || any(is.null(.reference.rate))) {
48-
print(paste("meanDS::perf::numeric::0 ", .current.rate, 0.5, 2.0))
49-
perf.reference.save("meanDS::perf::numeric::0", .current.rate, 0.5, 2.0)
48+
print(paste("meanDS::perf::numeric::0 ", .current.rate, perf.profile.tolerance.lower(), perf.profile.tolerance.upper()))
49+
perf.reference.save("meanDS::perf::numeric::0", .current.rate, perf.profile.tolerance.lower(), perf.profile.tolerance.upper())
5050
} else {
5151
print(paste("meanDS::perf::numeric::0 ", format(.current.rate, digits = 8), ", ", format(100.0 * .current.rate / .reference.rate, digits = 4), "%", sep = ''))
5252
}
@@ -80,8 +80,8 @@ test_that("numeric meanDS, with NA - performance", {
8080
.current.rate <- .count / (difftime(.current.time, .start.time, units = "secs")[[1]])
8181
.reference.rate <- perf.reference.rate("meanDS::perf::numberAndNA::0")
8282
if (any(length(.reference.rate) == 0) || any(is.null(.reference.rate))) {
83-
print(paste("meanDS::perf::numberAndNA::0 ", .current.rate, 0.5, 2.0))
84-
perf.reference.save("meanDS::perf::numberAndNA::0", .current.rate, 0.5, 2.0)
83+
print(paste("meanDS::perf::numberAndNA::0 ", .current.rate, perf.profile.tolerance.lower(), perf.profile.tolerance.upper()))
84+
perf.reference.save("meanDS::perf::numberAndNA::0", .current.rate, perf.profile.tolerance.lower(), perf.profile.tolerance.upper())
8585
} else {
8686
print(paste("meanDS::perf::numberAndNA::0 ", format(.current.rate, digits = 8), ", ", format(100.0 * .current.rate / .reference.rate, digits = 4), "%", sep = ''))
8787
}

tests/testthat/test-perf-varDS.R

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -45,8 +45,8 @@ test_that("numeric varDS - performance", {
4545
.current.rate <- .count / (difftime(.current.time, .start.time, units = "secs")[[1]])
4646
.reference.rate <- perf.reference.rate("varDS::perf::numeric::0")
4747
if (any(length(.reference.rate) == 0) || any(is.null(.reference.rate))) {
48-
print(paste("varDS::perf::numeric::0 ", .current.rate, 0.5, 2.0))
49-
perf.reference.save("varDS::perf::numeric::0", .current.rate, 0.5, 2.0)
48+
print(paste("varDS::perf::numeric::0 ", .current.rate, perf.profile.tolerance.lower(), perf.profile.tolerance.upper()))
49+
perf.reference.save("varDS::perf::numeric::0", .current.rate, perf.profile.tolerance.lower(), perf.profile.tolerance.upper())
5050
} else {
5151
print(paste("varDS::perf::numeric::0 ", format(.current.rate, digits = 8), ", ", format(100.0 * .current.rate / .reference.rate, digits = 4), "%", sep = ''))
5252
}
@@ -80,8 +80,8 @@ test_that("numeric varDS, with NA - performance", {
8080
.current.rate <- .count / (difftime(.current.time, .start.time, units = "secs")[[1]])
8181
.reference.rate <- perf.reference.rate("varDS::perf::numberAndNA::0")
8282
if (any(length(.reference.rate) == 0) || any(is.null(.reference.rate))) {
83-
print(paste("varDS::perf::numberAndNA::0 ", .current.rate, 0.5, 2.0))
84-
perf.reference.save("varDS::perf::numberAndNA::0", .current.rate, 0.5, 2.0)
83+
print(paste("varDS::perf::numberAndNA::0 ", .current.rate, perf.profile.tolerance.lower(), perf.profile.tolerance.upper()))
84+
perf.reference.save("varDS::perf::numberAndNA::0", .current.rate, perf.profile.tolerance.lower(), perf.profile.tolerance.upper())
8585
} else {
8686
print(paste("varDS::perf::numberAndNA::0 ", format(.current.rate, digits = 8), ", ", format(100.0 * .current.rate / .reference.rate, digits = 4), "%", sep = ''))
8787
}

0 commit comments

Comments
 (0)