Hello Iago,

Before being saved to RDS, farr is a wrapper ALTREP; it contains a
reference to the array, and a separate list of attributes including the
class and dims. This avoids having to copy arr just to add some attributes.
After being loaded from RDS, farr is not ALTREP; all of its attributes are
attached to the array as normal.

farr1 <- new('farray', arr)
farr_rds <- tempfile(fileext = ".rds")
saveRDS(new('farray', arr), file = farr_rds)
farr2 <- readRDS(farr_rds)

.Internal(inspect(farr1, max.depth = 1))
#> @7fd96c7c4d80 14 REALSXP g0c0 [OBJ,MARK,REF(3),S4,gp=0x10,ATT]  wrapper
[srt=-2147483648,no_na=0]
#>   @7fd976272000 14 REALSXP g0c7 [MARK,REF(8),ATT] (len=320000, tl=0)
0.0586121,0.335355,0.365133,0.492381,0.0354994,...
#>   ATTRIB:
#>     @7fd9741a4f60 02 LISTSXP g0c0 [MARK,REF(1)]
#> ATTRIB:
#>   @7fd96c7c4c68 02 LISTSXP g0c0 [MARK,REF(1)]
#>       ...

.Internal(inspect(farr2, max.depth = 1))
#> @7fd9764e4000 14 REALSXP g0c7 [OBJ,REF(1),S4,gp=0x10,ATT] (len=320000,
tl=0) 0.0586121,0.335355,0.365133,0.492381,0.0354994,...
#> ATTRIB:
#>   @7fd96fc30a10 02 LISTSXP g0c0 [REF(1)]
#>       ...

Using tracemem() on the array object (which is arr for farr1, and just
farr2 itself for farr2) shows that the array is copied once when subsetting
farr2, but not when subsetting farr1.

tracemem(arr)
#> [1] "<0x7fd976272000>"
sub1 <- farr1[1,1,1,1,1,1]

tracemem(farr2)
#> [1] "<0x7fd9764e4000>"
sub2 <- farr2[1,1,1,1,1,1]
#> tracemem[0x7fd9764e4000 -> 0x7fd976756000]: getDataPart .local [

The copying happens during getDataPart(), i.e., [email protected]. As I understand
it, for farr2, getDataPart() needs to strip the class attribute from the
array, requiring it to copy the array. But for farr1, the class attribute
is attached to the ALTREP object and not the array itself, so getDataPart()
does not need to strip the class attribute from the array and does not need
to copy it.

I'd be interested to hear any suggestions to avoid copying the array here.

Cheers,

Ian

____
Ian Farm
Laboratory Manager, The Agroecology Lab & Soil Functions and Trajectories
Lab
University of Maine School of Food and Agriculture
5762 Roger Clapp Greenhouses, Orono, Maine 04469

On Thu, Mar 12, 2026 at 7:01 AM Mosqueira Sanchez, Iago via R-devel <
[email protected]> wrote:

> An S4 class based on an array, but with a fixed number of dimensions,
> requires overloading the '[' method so that drop=FALSE even when single
> elements are selected in one of them.
>
> This works well, but once the S4 object is saved to a file and then loaded,
> the speed drops greatly (20 times larger, code below), while memory usage
> increases from 0 to 2.5 Mb.
>
> What could be causing this? Is there anything that can be done to avoid
> this
> penalty?
>
> Is the difference in timing between array and the S4 class just due to the
> S4 system? Using callNextMethod() inside the '[' method made it faster but
> not if called with all arguments specified, as needed to override the
> drop=TRUE default.
>
> Are there any suggestions of a better mechanism than the call to
>
> [email protected] <- [email protected][i, j, k, l, m, n, drop=FALSE]
>
> the method is using?
>
> Many thanks,
>
>
> Iago
>
>
> # Set farray class, a 6D array
> setClass("farray",      representation("array"),
>         prototype(array(as.numeric(NA), dim=c(1,1,1,1,1,1)))
> )
>
> # Overload '[' to ensure drop=FALSE
> setMethod("[", signature(x="farray"),
>     function(x, i, j, k, l, m, n, ..., drop=FALSE) {
>       [email protected] <- [email protected][i, j, k, l, m, n, drop=FALSE]
>       return(x)
>   }
> )
>
> # Example array
> arr <- array(
>   runif(prod(c(10, 20, 2, 4, 2, 100))),
>   dim = c(10, 20, 2, 4, 2, 100),
>   dimnames = list(a=seq(10), b=seq(20), c=seq(2), d=seq(4), e=seq(2),
> f=seq(100))
> )
>
> # Example farray
> farr <- new('farray', arr)
>
> # Save farr
> saveRDS(farr, file='farr.rds')
>
> # Check speed
> library(microbenchmark)
>
> library(bench)
>
> # array
> microbenchmark(arr[1,1,1,1,1,1], times=500L, unit='us')
> bench::mark(arr[1,1,1,1,1,1])
>
> # remove and load
> rm(farr)
> farr <- readRDS('farr.rds')
> microbenchmark(farr[1,1,1,1,1,1], times=500L, unit='us')
> bench::mark(farr[1,1,1,1,1,1])
>
>
>
> --
> Iago Mosqueira
>
> Wageningen Marine Research
>
> Haringkade 1
> Postbus 68
> 1976CP, IJmuiden
> The Netherlands
>
> Tel.: +31 (0)317 488 995
> [email protected]
> ______________________________________________
> [email protected] mailing list
> https://stat.ethz.ch/mailman/listinfo/r-devel
>

        [[alternative HTML version deleted]]

______________________________________________
[email protected] mailing list
https://stat.ethz.ch/mailman/listinfo/r-devel

Reply via email to