system.time() 与 proc.time()
测量 R 表达式经过的时间、用户时间和系统时间
system.time() 与 proc.time() 是 CoddyKit 上的免费 R Academy 课时。 这是第 1 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 R Academy 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 R Academy 课程共包含 4 节课。
为什么要测量性能
在优化代码之前,您需要先测量它。猜测代码变慢的原因会导致无谓的工作。R 提供了用于精确测量表达式耗时的内置工具。
三个主要工具是 system.time()、proc.time() 和 Sys.time()。它们分别用于性能分析中的不同目的。
system.time() 基础
system.time(expr) 会执行一个表达式,并返回其耗时。这是在 R 中测量单个操作耗时的最简单方法。
返回结果是一个属于 proc_time 类的对象,其中包含可供检查的命名元素。
result <- system.time({
x <- 1:1000000
total <- sum(x)
})
print(result)读取三个时间值
system.time() 会返回五个值,但其中三个最为重要:
- user — R 代码本身使用的 CPU 时间
- sys — 操作系统代表 R 使用的 CPU 时间
- elapsed — 墙上时钟时间(实际经过的秒数)
通常最值得关注的是 elapsed。在多核计算机上,user + sys 可能大于 elapsed。
t <- system.time(Sys.sleep(0.1))
cat('user :', t['user.self'], '
')
cat('sys :', t['sys.self'], '
')
cat('elapsed:', t['elapsed'], '
')使用 proc.time() 手动计时
proc.time() 会以快照形式返回当前的 CPU 时间和经过时间。通过分别在代码块前后获取快照,您可以测量任意代码片段的耗时。
用结束快照减去开始快照,即可得到该部分代码的经过时间。
start <- proc.time()
for (i in 1:100000) sqrt(i)
end <- proc.time()
diff <- end - start
cat('elapsed:', diff['elapsed'], 'seconds
')proc.time() 的组成部分
proc.time() 会返回一个包含三个元素的命名数值向量:
user.self— R 进程使用的用户 CPU 时间sys.self— R 进程使用的系统 CPU 时间elapsed— 自 R 启动以来的墙上时钟时间
两次调用 proc.time() 的差值可以提供有意义的耗时变化。
pt <- proc.time()
cat('Names:', names(pt), '
')
cat('Values:', pt, '
')
cat('Class:', class(pt), '
')使用 Sys.time() 获取墙上时钟时间戳
Sys.time() 会以 POSIXct 对象的形式返回当前日期和时间。与 proc.time() 不同,它提供的是现实世界中的时间戳,而不只是 CPU 使用时间。
当您需要记录某件事发生的时间,而不仅是它耗时多久时,这一工具非常有用。
start_time <- Sys.time()
cat('Start:', format(start_time), '
')
Sys.sleep(0.05)
end_time <- Sys.time()
cat('End :', format(end_time), '
')使用 difftime() 测量时间间隔
difftime(end, start, units='secs') 会计算两个 POSIXct 时间戳之间的差值。您可以选择以下单位:'secs'、'mins'、'hours'、'days'。
它与 Sys.time() 搭配使用,可以自然地生成易读的计时输出。
t1 <- Sys.time()
x <- cumsum(1:500000)
t2 <- Sys.time()
delta <- difftime(t2, t1, units = 'secs')
cat('Time taken:', round(as.numeric(delta), 4), 'seconds
')使用 replicate() 循环计时
由于垃圾回收或操作系统调度的影响,单次计时结果可能会有所不同。replicate(n, system.time(expr)['elapsed']) 会多次运行该表达式,并返回一个包含各次经过时间的向量。
对多次计时结果取中位数,可以得到更稳定的估计值。
times <- replicate(10, system.time({
x <- rnorm(10000)
mean(x)
})['elapsed'])
cat('Median elapsed:', median(times), 'seconds
')
cat('Range:', range(times), '
')比较两种方法
使用 system.time() 可以直接比较同一任务的两种实现方式。在决定采用某种方法之前,这种模式有助于确认其中一种确实更快。
n <- 100000
t_loop <- system.time({
result <- numeric(n)
for (i in seq_len(n)) result[i] <- i^2
})['elapsed']
t_vec <- system.time({
result <- seq_len(n)^2
})['elapsed']
cat('Loop :', t_loop, 's
')
cat('Vector :', t_vec, 's
')
cat('Speedup:', round(t_loop / max(t_vec, 1e-6), 1), 'x
')测量嵌套操作的耗时
您可以嵌套调用 system.time(),或在工作流中使用 proc.time() 检查点,从而找出哪个步骤是瓶颈。
随着脚本运行打印中间差值,可以为您的流水线建立时间线。
p0 <- proc.time()
x <- rnorm(200000)
p1 <- proc.time()
y <- sort(x)
p2 <- proc.time()
z <- cumsum(y)
p3 <- proc.time()
cat('Generate:', (p1-p0)['elapsed'], 's
')
cat('Sort :', (p2-p1)['elapsed'], 's
')
cat('Cumsum :', (p3-p2)['elapsed'], 's
')计时实用技巧
测量 R 代码耗时时,请牢记以下做法:
- 计时前先运行一次代码,以预热 JIT 和文件缓存
- 计时前使用
gc(),以重置垃圾回收状态 - 多次运行时优先使用中位数而不是平均值——垃圾回收产生的离群值会使平均值偏离
- 测量瓶颈,而不是整个脚本
gc() # clear garbage before timing
times <- replicate(5, system.time({
m <- matrix(rnorm(1000 * 1000), nrow = 1000)
crossprod(m)
})['elapsed'])
cat('Median:', median(times), 's
')快速检查:system.time() 的组成部分
system.time() 的哪个组成部分表示执行期间实际经过的墙上时钟秒数?
性能计时回顾
现在,您已经掌握了 R 基础包中的三个互补计时工具:
system.time(expr)— 测量单个表达式耗时的最快方法;返回 user/sys/elapsedproc.time()— 基于快照测量任意代码块的耗时Sys.time()+difftime()— 获取墙上时钟时间戳和易于理解的时间间隔
在对性能下结论之前,请使用 replicate() 获取稳定的中位数计时结果。
用 AI 导师学习 R — 免费
在浏览器中编写并运行真实代码,获得全天候 AI 导师的即时帮助,并在网页或应用中继续学习。
- 课程
- 43
- 课程
- 159
常见问题解答
「system.time() 与 proc.time()」课时是免费的吗?
是的 — 「system.time() 与 proc.time()」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 R Academy 课程的其余内容,请升级到 CoddyKit PRO。 R Academy 课程共包含 4 节课。
「system.time() 与 proc.time()」这节课中我会学到什么?
测量 R 表达式经过的时间、用户时间和系统时间 你通过在浏览器中直接运行的动手代码来练习 R Academy,全天候 AI 导师会在你学习这节课的过程中回答你的问题。
学习 R Academy 需要有经验吗?
无需任何先前经验。CoddyKit 上的 R Academy 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 1 节课,共 4 节。
「system.time() 与 proc.time()」课时需要多长时间?
大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。
我能在这节 R Academy 课中编写并运行代码吗?
能。每节 R Academy 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。
此课程中的所有课时
- system.time() 与 proc.time()
- 使用 Rprof 和 profvis 分析代码性能
- 用向量化提升速度
- 使用 microbenchmark 进行基准测试