Skip to content

[Bioc-devel] S4 Method Slow Execution if Signature Has Multiple Class Unions

3 messages · Dario Strbenac, Michael Lawrence

#
Good day,

I created two constructor methods for a generic function. One is for the default empty constructor and the other is a constructor when any one or more parameters is specified by the user. The method signatures are:

1. c("missing", "missing", "missing", "missing", "missing", "missing", "missing", "missing"),
2. c("characterOrMissing", "numericOrMissing", "numericOrMissing", "numericOrMissing", "numericOrMissing", "characterOrMissing", "BiocParallelParamOrMissing", "numericOrMissing")

The class unions are defined as you might expect.

setClassUnion("characterOrMissing", c("character", "missing"))
setClassUnion("numericOrMissing", c("numeric", "missing"))
setClassUnion("BiocParallelParamOrMissing", c("BiocParallelParam", "missing"))

The first method works as expected:
user  system elapsed 
  0.165   0.000   0.165

The second takes over ten minutes and constantly uses 100% CPU usage, according to top.
user  system elapsed 
760.018  15.093 775.090

Strangely, if I rerun this code again, it works quickly the second time.
user  system elapsed 
  0.145   0.000   0.145

I haven't been able to come up with a minimal reproducile example of the issue. How can this be done consistently and efficiently?

--------------------------------------
Dario Strbenac
University of Sydney
Camperdown NSW 2050
Australia
#
Hi Dario,

Thanks for bringing this up. The second time speed could be explained
by the caching that happens inside the methods package. If you are
able to come up with a smaller reproducible example, I would be happy
to help out.

Michael

On Mon, Nov 22, 2021 at 1:00 PM Dario Strbenac via Bioc-devel
<bioc-devel at r-project.org> wrote:

  
    
#
Hello,

Thanks. It was difficult to pinpoint, but I was able to make a minimal example. It happens only if SummarizedExperiment is pre-loaded. The difference is 0.2 seconds versus 32 seconds on my modest Windows 10 laptop computer - a 150 times slowdown. Can you reproduce it?

library(SummarizedExperiment)

setClassUnion("characterOrMissing", c("character", "missing"))
setClassUnion("integerOrMissing", c("integer", "missing"))
setClass("ParamsSet", representation(A = "characterOrMissing", B = "integer"))
setGeneric("ParamsSet", function(A, B, C, D, E, F, G, H) standardGeneric("ParamsSet"))

setMethod("ParamsSet", c("missing", "missing", "missing", "missing", "missing", "missing", "missing", "missing"),
function() # Empty constructor
{
  new("ParamsSet", A = 'M', B = 300L)
})

setMethod("ParamsSet", c("characterOrMissing", "integerOrMissing", "integerOrMissing", "integerOrMissing",
                         "characterOrMissing", "integerOrMissing", "integerOrMissing", "integerOrMissing"),
function(A = c('L', 'M', 'N'), B = 500, C = 100, D, E, F, G, H)
{
  if(missing(A)) A <- 'L' # Mimick match.arg.
  if(missing(B)) B <- 500L # Hack to implement parameter defaults not specified by generic.
  if(missing(C)) C <- 100L
  new("ParamsSet", A = A, B = B)
})

system.time(ParamsSet(B = 999L)) # Slow or fast, depending on SummarizedExperiment presence.

--------------------------------------
Dario Strbenac
University of Sydney
Camperdown NSW 2050
Australia