Logger is messing with my package in an unexpected way, causing severe slowdowns for apparently no reason.
In the following, function f is called via do.call with a moderately big object as parameter. Note that f does not actually evaluate the object. As the object size increases, logger slows the function down.
The slow down does not happen, or not as severely :
when log_info is replaced by cat
with the default layout
outside of do.call
It may be that I am using the layout factory in an unconventionnal and unexpeced way but unfortunately I wasn't able to find many examples of custom layouts with logger. But setting the layout back to default (glue layout) does not work either.
Reproducible example
dt <- data.frame(
age = 0:19,
nmb = runif(20),
sex = sample(c("M", "F"), 20, replace=TRUE),
gen = 1962:1943
)
h <- function(dt, use_logger = TRUE){
if(use_logger) logger::log_info("With logger") else cat("Without logger")
}
n <- nrow(dt)
N <- 1000000
# 10 exponentially distributed data sizes between n and N
rep <- 10
ns <- floor(exp(seq(log(n),log(N),length.out=rep)))
# default layout works [exponential but small]
for(i in 1:rep){
elts <- sample.int(n, ns[i], replace = TRUE)
t0 <- Sys.time()
do.call('h', args=list(dt = dt[elts,]))
cat("Size:", ns[i], fill=TRUE)
cat("Time:", as.numeric(Sys.time()-t0, units = "secs")*10^3, "ms", fill=TRUE)
cat("-------", fill=TRUE)
}
#> Size: 19
#> Time: 9.083986 ms
#> -------
#> Size: 66
#> Time: 1.929045 ms
#> -------
#> Size: 221
#> Time: 0.4019737 ms
#> -------
#> Size: 736
#> Time: 0.5950928 ms
#> -------
#> Size: 2451
#> Time: 1.213074 ms
#> -------
#> Size: 8157
#> Time: 6.584167 ms
#> -------
#> Size: 27144
#> Time: 12.65001 ms
#> -------
#> Size: 90320
#> Time: 46.97299 ms
#> -------
#> Size: 300533
#> Time: 270.5541 ms
#> -------
#> Size: 999999
#> Time: 898.0708 ms
#> -------
logger::log_layout(
logger::layout_glue_generator(
format = paste(
"{crayon::white(format(time, '%Hh%M:%S'))}",
"{if(levelr<=logger::WARN)",
"crayon::bold(colorize_by_log_level(paste0('[', level, '] '), levelr))",
"else ''}",
"{grayscale_by_log_level(msg, levelr)}"
)
)
)
# direct call works [log linear times]
for(i in 1:rep){
elts <- sample.int(n, ns[i], replace = TRUE)
t0 <- Sys.time()
h(dt = dt[elts,])
cat("Size:", ns[i], fill=TRUE)
cat("Time:", as.numeric(Sys.time()-t0, units = "secs")*10^3, "ms", fill=TRUE)
cat("-------", fill=TRUE)
}
#> Size: 19
#> Time: 63.57002 ms
#> -------
#> Size: 66
#> Time: 1.726151 ms
#> -------
#> Size: 221
#> Time: 2.178192 ms
#> -------
#> Size: 736
#> Time: 1.669168 ms
#> -------
#> Size: 2451
#> Time: 1.455069 ms
#> -------
#> Size: 8157
#> Time: 1.461983 ms
#> -------
#> Size: 27144
#> Time: 1.727104 ms
#> -------
#> Size: 90320
#> Time: 2.158165 ms
#> -------
#> Size: 300533
#> Time: 2.237797 ms
#> -------
#> Size: 999999
#> Time: 2.264023 ms
#> -------
# works without using logger [exponential increase but soooooo small]
for(i in 1:rep){
elts <- sample.int(n, ns[i], replace = TRUE)
t0 <- Sys.time()
do.call('h', args=list(dt = dt[elts,], use_logger = FALSE))
cat("Size:", ns[i], fill=TRUE)
cat("Time:", as.numeric(Sys.time()-t0, units = "secs")*10^3, "ms", fill=TRUE)
cat("-------", fill=TRUE)
}
#> Without loggerSize: 19
#> Time: 0.1070499 ms
#> -------
#> Without loggerSize: 66
#> Time: 0.09202957 ms
#> -------
#> Without loggerSize: 221
#> Time: 0.1518726 ms
#> -------
#> Without loggerSize: 736
#> Time: 0.3318787 ms
#> -------
#> Without loggerSize: 2451
#> Time: 0.980854 ms
#> -------
#> Without loggerSize: 8157
#> Time: 3.11017 ms
#> -------
#> Without loggerSize: 27144
#> Time: 11.02495 ms
#> -------
#> Without loggerSize: 90320
#> Time: 38.38015 ms
#> -------
#> Without loggerSize: 300533
#> Time: 137.5451 ms
#> -------
#> Without loggerSize: 999999
#> Time: 617.265 ms
#> -------
# logger in do.call fails [note stop after 5 steps]
for(i in 1:5){
elts <- sample.int(n, ns[i], replace = TRUE)
t0 <- Sys.time()
do.call('h', args=list(dt = dt[elts,]))
cat("Size:", ns[i], fill=TRUE)
cat("Time:", as.numeric(Sys.time()-t0, units = "secs")*10^3, "ms", fill=TRUE)
cat("-------", fill=TRUE)
}
#> Size: 19
#> Time: 2.557993 ms
#> -------
#> Size: 66
#> Time: 3.441811 ms
#> -------
#> Size: 221
#> Time: 16.80613 ms
#> -------
#> Size: 736
#> Time: 156.4329 ms
#> -------
#> Size: 2451
#> Time: 2251.328 ms
#> -------
# moving back to default deos not help [note stop after 5 steps]
logger::log_layout(
logger::layout_glue
)
for(i in 1:5){
elts <- sample.int(n, ns[i], replace = TRUE)
t0 <- Sys.time()
do.call('h', args=list(dt = dt[elts,]))
cat("Size:", ns[i], fill=TRUE)
cat("Time:", as.numeric(Sys.time()-t0, units = "secs")*10^3, "ms", fill=TRUE)
cat("-------", fill=TRUE)
}
#> Size: 19
#> Time: 2.715826 ms
#> -------
#> Size: 66
#> Time: 4.930019 ms
#> -------
#> Size: 221
#> Time: 17.84205 ms
#> -------
#> Size: 736
#> Time: 183.4199 ms
#> -------
#> Size: 2451
#> Time: 2523.912 ms
#> -------
Logger is messing with my package in an unexpected way, causing severe slowdowns for apparently no reason.
In the following, function
f
is called viado.call
with a moderately big object as parameter. Note thatf
does not actually evaluate the object. As the object size increases, logger slows the function down.The slow down does not happen, or not as severely :
log_info
is replaced bycat
do.call
It may be that I am using the layout factory in an unconventionnal and unexpeced way but unfortunately I wasn't able to find many examples of custom layouts with
logger
. But setting the layout back to default (glue layout) does not work either.Reproducible example
Created on 2024-09-10 with reprex v2.1.1