Skip to content

Commit

Permalink
Add asymptoticMemoryUsage (+ docs/unit-tests)
Browse files Browse the repository at this point in the history
For additional details, check this thread:
#6
  • Loading branch information
Anirban166 committed Jun 11, 2020
1 parent 825dc54 commit 03bfd53
Show file tree
Hide file tree
Showing 3 changed files with 85 additions and 1 deletion.
2 changes: 1 addition & 1 deletion DESCRIPTION
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ License: MIT + file LICENSE
Encoding: UTF-8
LazyData: true
RoxygenNote: 6.1.1
Imports: boot, microbenchmark, ggplot2, stats
Imports: boot, microbenchmark, bench, ggplot2, stats
Suggests:
testthat (>= 2.1.0),
covr
58 changes: 58 additions & 0 deletions R/asymptoticMemoryUsage.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
#' Function to compute benchmarked memory allocation with different data sizes for an R expression
#'
#' @title Asymptotic Memory Metrics Quantifying function
#'
#' @param e An expression which is in the form of a function operating on the parameter 'data.sizes' given by the user.
#'
#' @param data.sizes Set of data sizes, which should preferably be a sequence of powers of ten, with a multitude of mid-values included.
#' # Example: data.sizes = 10^(1, 5, by = 0.1)
#'
#' @param max.bytes The maximum number of allocated bytes an iteration would be limited upto for the passed expression. (once the limit has been exceeded, further computations on incrementally larger dataset sizes won't be done)
#'
#' @return A data frame comprising of the memory usage (in megabytes) computed by bench and the corresponding dataset sizes.
#'
#' @export
#' @import bench

asymptoticMemoryUsage <- function(e, data.sizes, max.bytes)
{
if(!all(!is.infinite(data.sizes) & !is.na(data.sizes) & !is.nan(data.sizes)))
{
stop("data.sizes must not contain any NA/NaN/Infinite value.")
}

if(length(data.sizes) == 0)
{
stop("Cannot run on an empty vector for 'data.sizes'.")
}

lang.obj <- substitute(e)

fun.obj <- function(data.sizes)
{
eval(lang.obj)
}

memory.size.limit = ifelse(missing(max.bytes), 10^6, max.bytes)

l <- length(data.sizes)

memory.metrics.list <- list()

for(i in 1:l)
{
benchmarked.memory.size <- bench_memory(fun.obj(data.sizes[i]))$mem_alloc

data.size <- data.sizes[i]

memory.metrics.list[[i]] <- data.frame(c(benchmarked.memory.size), c(data.size))

ifelse((benchmarked.memory.size > memory.size.limit), break, next)
}

resultant.df <- do.call(rbind, memory.metrics.list)

colnames(resultant.df) <- c("Memory usage", "Data sizes")

return(resultant.df)
}
26 changes: 26 additions & 0 deletions tests/testthat/test-testsfortestComplexity.R
Original file line number Diff line number Diff line change
Expand Up @@ -50,3 +50,29 @@ test_that("Return value (ggplot object) test for plotTimings", {
expect_true("ggplot" %in% attributes(plotTimings(df))$class)
})

# Tests for asymptoticMemoryUsage

test_that("Empty vector/sequence test for data.sizes", {
expect_error(asymptoticMemoryUsage(expression, data.sizes = c()))
expect_error(asymptoticMemoryUsage(expression, data.sizes = c(NULL)))
})

test_that("NA test for data.sizes", {
expect_error(asymptoticMemoryUsage(expression, data.sizes = c(NA)))
})

test_that("NaN test for data.sizes", {
expect_error(asymptoticMemoryUsage(expression, data.sizes = sqrt(-1)))
})

test_that("Inf test for data.sizes", {
expect_error(asymptoticMemoryUsage(expression, data.sizes = Inf))
})

test_that("Return value test for asymptoticMemoryUsage", {
df <- asymptoticMemoryUsage(rpois(data.sizes, 10), data.sizes = 10)
expect_that(df, is_a("data.frame") )
expect_equal(dim(df), c(1, 2))
expect_equal(attributes(df)$names, c("Memory usage", "Data sizes"))
})

0 comments on commit 03bfd53

Please sign in to comment.