如何封装microbenchmark实现data.table与dplyr的性能对比(含拷贝耗时修正)
封装data.table与dplyr重命名列的性能测试逻辑
需求背景
需要对比data.table和dplyr重命名列的操作速度,获取两者的中位数耗时及相对耗时。由于data.table采用引用修改机制,测试时必须在内部拷贝对象,因此需要扣除拷贝操作的额外耗时,同时避免重复编写统计逻辑导致的脚本冗余。
封装后的解决方案
将测试运行、拷贝耗时扣除、相对时间计算的逻辑封装为可复用函数,利用...参数灵活传递测试表达式,适配不同场景:
1. 封装性能测试函数
library(microbenchmark) library(dplyr) library(data.table) benchmark_with_copy_overhead <- function(..., copy_expr_name = "copyOverhead") { # 执行微基准测试 res <- microbenchmark(..., unit = "ms") # 转换为data.table格式并生成汇总统计 res_summary <- setDT(summary(res)) # 获取拷贝操作的中位数耗时 copy_median <- res_summary[expr == copy_expr_name, median] # 扣除data.table测试的拷贝开销,保留目标测试项 res_adjusted <- res_summary[expr != copy_expr_name, .( test = expr, median_ms = median - ifelse(expr == "data.table", copy_median, 0) )] # 计算相对耗时(以最快项为基准) min_median <- min(res_adjusted$median_ms) res_adjusted[, relative_time := median_ms / min_median] return(res_adjusted[]) }
2. 使用函数进行重命名测试
# 准备测试数据集 DT <- as.data.table(datasets::swiss, keep.rownames = TRUE) Tib <- tibble::as_tibble(tibble::rownames_to_column(datasets::swiss)) # 调用函数执行测试 test_result <- benchmark_with_copy_overhead( data.table = setnames(copy(DT), old = "rn", new = "Region"), copyOverhead = copy(DT), dplyr = rename(Tib, Region = rowname), times = 100 ) # 查看结果 print(test_result)
函数特性说明
- 灵活性:通过
...参数直接传递microbenchmark的测试表达式,可轻松扩展到其他需要扣除拷贝开销的data.table性能测试 - 自动处理拷贝开销:默认识别名为
copyOverhead的测试项,若拷贝项命名不同,可通过copy_expr_name参数指定 - 自动统计:自动计算调整后的中位数耗时和相对耗时,无需手动编写重复的统计逻辑
内容的提问来源于stack exchange,提问作者Maharero
相关产品推荐
相关产品推荐

