0Pricing
R Academy · Урок

system.time() и proc.time()

Измеряйте прошедшее, пользовательское и системное время выполнения выражений R

«system.time() и proc.time()» — бесплатный урок R Academy на CoddyKit. Это урок 1 из 4. Ты можешь прочитать весь урок бесплатно ниже — а потом практиковать его прямо в браузере с встроенным редактором кода и ИИ-репетитором 24/7. Это часть пути обучения 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 — время CPU, использованное непосредственно кодом R
  • sys — время CPU, использованное операционной системой от имени R
  • 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 — пользовательское время CPU процесса R
  • sys.self — системное время CPU процесса R
  • 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/elapsed
  • proc.time() — измерение времени произвольных блоков кода на основе снимков
  • Sys.time() + difftime() — отметки календарного времени и понятные человеку интервалы

Используйте replicate(), чтобы получить стабильные значения медианного времени, прежде чем делать выводы о производительности.

Часто задаваемые вопросы

Урок «system.time() и proc.time()» бесплатный?

Да — полный текст урока «system.time() и proc.time()» бесплатно доступен здесь в веб-версии. Чтобы практиковать его интерактивно (встроенный редактор кода и ИИ-репетитор 24/7) и разблокировать остальной курс R Academy, подпишись на CoddyKit PRO. Курс R Academy содержит 4 уроков всего.

Чему я научусь в уроке «system.time() и proc.time()»?

Измеряйте прошедшее, пользовательское и системное время выполнения выражений R Ты практикуешь R Academy с помощью реального кода, который запускаешь прямо в браузере, и ИИ-репетитор 24/7 отвечает на твои вопросы во время урока.

Нужен ли мне опыт, чтобы начать R Academy?

Предыдущий опыт не требуется. R Academy на CoddyKit структурирован для всех уровней — от новичков до продвинутых, поэтому ты можешь начать отсюда или с самого начала и учиться в своем темпе. Это урок 1 из 4.

Сколько времени занимает урок «system.time() и proc.time()»?

Большинство уроков CoddyKit занимают около 5–10 минут. Каждый из них компактный и интерактивный, поэтому ты постоянно делаешь прогресс и продолжаешь с того же места в веб-версии и приложении.

Можно ли писать и запускать код в этом уроке R Academy?

Да. Каждый урок R Academy включает встроенный редактор кода, поэтому ты пишешь и запускаешь реальный код прямо в браузере и получаешь моментальную обратную связь от AI — локальная установка не требуется.

Все уроки этого курса

  1. system.time() и proc.time()
  2. Профилирование кода с помощью Rprof и profvis
  3. Векторизация для ускорения
  4. Бенчмаркинг с помощью microbenchmark
← Назад к R Academy