r - 为什么以下函数的性能不会因增加一个额外的对象而受到惩罚?
问题描述
下面我有三个执行相同操作的函数 - 复制给定的 data.frame 并将rbind
其复制到自身(即增长对象的不良做法)。
第一个函数f1
将输入对象复制到一个新对象x
,然后增长该对象,最后替换输入对象。
第二个函数f2
将输入对象复制到一个新对象 中x
,然后增长输入对象。
第三个函数f3
仅增长输入对象。
f1
考虑到它本质上需要更改df
和的内存分配,我本来预计会是最慢的x
。相反,所有 3 个函数的计算时间似乎大致相等。我如何理解这种行为?我的例子有缺陷吗?
## Functions
# copy df, grow copy, replace df with copy
f1 <- function(df){
x <- df
x <- rbind(x, x)
df <- x
return(df)
}
# copy df, grow df
f2 <- function(df){
x <- df
df <- rbind(df, x)
return(df)
}
# grow df
f3 <- function(df){
df <- rbind(df, df)
return(df)
}
## Benchmark
df <- rbind(iris)
res <- microbenchmark(f1(df), f2(df), f3(df), times=5000L)
## Print results:
print(res)
# Unit: microseconds
# expr min lq mean median uq max neval
# f1(df) 255.66 263.591 292.6851 270.123 292.516 2693.291 5000
# f2(df) 255.66 263.591 302.5159 270.590 292.516 15460.876 5000
# f3(df) 255.66 263.591 299.6157 270.122 292.516 3613.758 5000
## Plot results:
boxplot(res)
解决方案
R 函数使用修改时复制。所以,当你df
作为参数传递时,如果你不修改它,它将指向你传递的同一个对象(同一个地址)。
如果您分配给同一个对象,也会发生同样的情况。例如,使用address <- function(x) cat(data.table::address(x), "\n")
:
> x <- 1
> address(x)
0x58164b8
> y <- x
> address(y)
0x58164b8
所以现在,在你的函数中打印一些地址
## Functions
# copy df, grow copy, replace df with copy
f1 <- function(df){
address(x <- df)
address(x <- rbind(x, x))
address(df <- x)
return(df)
}
# copy df, grow df
f2 <- function(df){
address(x <- df)
address(df <- rbind(df, x))
return(df)
}
结果:
> df <- rbind(iris)
> address(df)
0x543e378
> res1 <- f1(df)
0x543e378
0x5d3bd08
0x5d3bd08
> res2 <- f2(df)
0x543e378
0x5c89e40
因此,您的每个函数都只创建一个新对象,这就是它们具有相同足迹的原因。
推荐阅读
- python - 使用Python将单元格范围从Excel复制到另一个
- karate - 无法使用 leftOf 选中复选框
- c# - 发布期间出错 无法删除目录“bin\Debug\app.publish\ ClickOnce
- c++ - 在 g++ 中打印反斜杠 r (\r) 在 mac 终端上不起作用
- javascript - 仅在文本溢出时显示工具提示 - 材质 UI
- encryption - 我不明白有多少文件,我必须创建
- python - 使用 Pandas 根据另一列的值创建一列
- typescript - 打字稿:在 index.d.ts 中原型化的类在尝试使用构造函数时给出“x 不是构造函数”
- php - 带有模拟的 PHPUnit 测试覆盖率 API
- git - 提交到 git 时删除历史文件夹是否安全