如何从bench::mark的memory列获取更多内存基准测试详情
解决bench::mark内存列详情查看与内存优化建议
一、获取内存列的详细信息
bench::mark返回结果中的memory列是Rprofmem类型对象,直接打印仅显示摘要。要查看完整内存分配记录,将其转换为数据框即可:
# 先保存基准测试结果 bench_res <- bench::mark( iterations = 4, check = FALSE, "dplyr" = test_data %>% mutate(mean = rowMeans(.[, ColNum:length(.)], na.rm=T), var = row_sample_variance(.[, ColNum:length(.)], na.rm=T), SD = sqrt(var), "-95%" = mean -(1.96*SD), "+95%" = mean +(1.96*SD)), "Indvidual" = { rowMeans(test_data[, ColNum:length(test_data)], na.rm=T) row_sample_variance(test_data[, ColNum:length(test_data)], na.rm=T) sqrt(row_sample_variance(test_data[, ColNum:length(test_data)], na.rm=T)) rowMeans(test_data[, ColNum:length(test_data)], na.rm=T) -(1.96*sqrt(row_sample_variance(test_data[, ColNum:length(test_data)], na.rm=T))) rowMeans(test_data[, ColNum:length(test_data)], na.rm=T) +(1.96*sqrt(row_sample_variance(test_data[, ColNum:length(test_data)], na.rm=T))) }, "full dplyr" = test_data %>% mutate(mean = rowMeans(.[, ColNum:length(.)], na.rm=T), var = row_sample_variance(.[, ColNum:length(.)], na.rm=T), SD = sqrt(row_sample_variance(.[, ColNum:length(.)], na.rm=T)), "-95%" = rowMeans(.[, ColNum:length(.)], na.rm=T) -(1.96*sqrt(row_sample_variance(.[, ColNum:length(.)], na.rm=T))), "+95%" = rowMeans(.[, ColNum:length(.)], na.rm=T) +(1.96*sqrt(row_sample_variance(.[, ColNum:length(.)], na.rm=T)))) ) # 查看所有测试组的内存详情 lapply(bench_res$memory, as.data.frame) # 单独查看某一组(比如dplyr)的内存分配 as.data.frame(bench_res$memory[["dplyr"]])
转换后的数据框包含三列核心信息:
what:内存分配的对象类型(如矩阵、向量)bytes:分配的内存字节数trace:触发内存分配的调用栈,可定位高内存消耗的代码段
二、针对千万行数据集的内存优化建议
你的测试场景是千万行30列数据,当前代码存在重复计算和不必要的临时对象,这会大幅增加内存占用,以下是关键优化点:
1. 避免重复计算
当前"Indvidual"和"full dplyr"组重复调用rowMeans和row_sample_variance多次,每次调用都会生成临时对象。应复用中间结果减少内存开销:
# dplyr优化版:仅计算一次均值和方差 test_data %>% mutate(mean = rowMeans(.[, ColNum:length(.)], na.rm=T), var = row_sample_variance(.[, ColNum:length(.)], na.rm=T)) %>% mutate(SD = sqrt(var), "-95%" = mean - 1.96*SD, "+95%" = mean + 1.96*SD)
2. 优化方差计算函数
原row_sample_variance中x - rowMeans(x)会生成与输入同尺寸的临时矩阵,对千万行数据来说内存占用极高。改用方差的代数等价公式,避免大临时对象:
row_sample_variance_opt <- function(x, na.rm = FALSE) { n <- if (na.rm) rowSums(!is.na(x)) else ncol(x) # 处理n<=1的情况,避免除以0 n[n <= 1] <- 2 sum_x <- rowSums(x, na.rm = na.rm) sum_x2 <- rowSums(x^2, na.rm = na.rm) (n * sum_x2 - sum_x^2) / (n * (n - 1)) }
该版本仅计算行和与行平方和,内存占用远低于原函数。
3. 加入data.table对比
data.table在大数据集的内存控制和计算效率上表现更优,建议加入测试组:
library(data.table) test_dt <- as.data.table(test_data) bench::mark( iterations = 4, check = FALSE, "data.table" = test_dt[, `:=`( mean = rowMeans(.SD, na.rm = TRUE), var = row_sample_variance_opt(.SD, na.rm = TRUE) ), .SDcols = ColNum:ncol(test_dt)][, `:=`( SD = sqrt(var), "-95%" = mean - 1.96*SD, "+95%" = mean + 1.96*SD )] )
内容的提问来源于stack exchange,提问作者Maloccoda
相关产品推荐
相关产品推荐

