Оцените многострочный кодовый блок с помощью микробенчмарка

Можно ли оценить кодовый блок, состоящий из нескольких строк кода, с помощью микробенчмарка? Если да, то как?

Пример: у нас есть некоторые числовые данные в символьных столбцах:

testdata <- tibble::tibble(col1 = runif(1000), col2 = as.character(runif(1000)), col3 = as.character(runif(1000)))

Теперь мы можем попробовать разные способы их преобразования. Мы можем напрямую вызвать as.numeric для столбцов:

testdata$col2 <- as.numeric(testdata$col2)
testdata$col3 <- as.numeric(testdata$col3)

Мы могли бы попробовать сделать это внутри мутации dplyr:

testdata <- dplyr::mutate(testdata, col2 = as.numeric(col2),
               col3 = as.numeric(col3))

Или, может быть, мы знаем, что все столбцы должны быть числовыми, поэтому мы можем попробовать что-то менее явное, выполняющее некоторую проверку:

testdata <- dplyr::mutate_if(testdata, .predicate = is.character, .funs = as.numeric)

Теперь мы хотим сравнить производительность этих трех вариантов.

Последние 2 варианта являются отдельными вызовами, поэтому их можно легко протестировать в микробенчмарке, но первый вариант состоит из двух отдельных вызовов. Мы могли бы обернуть два вызова в функцию, а затем оценить ее в микротесте, но это приводит к небольшим накладным расходам функции, поэтому технически не оценивает решение, которое у нас есть сейчас. Мы можем включить вызовы отдельно в микробенчмарк, а затем добавить их после, так как среднее значение должно работать нормально, но для таких вещей, как минимум или максимум, это не обязательно дает разумные результаты.

Примеры в документации для microbenchmark в основном используют простые отдельные выражения и часто используют простую функцию для переноса кода.

Можно ли напрямую ввести несколько строк кода в микробенчмарк для совместной оценки?


person Marijn Stevering    schedule 27.12.2017    source источник


Ответы (1)


Заключив несколько строк кода в {} и разделив их ;, их можно оценить как один блок в микробенчмарке.

bench <- microbenchmark(separate = {as.numeric(testdata$col2); as.numeric(testdata$col3)},
                    mutate = dplyr::mutate(testdata, col2 = as.numeric(col2),
                                           col3 = as.numeric(col3)),
                    mutateif = dplyr::mutate_if(testdata, .predicate = is.character, .funs = as.numeric))

Что дает следующие результаты:

> bench
Unit: microseconds
     expr      min       lq      mean    median        uq        max neval
 separate  477.014  529.708  594.8982  576.4275  611.6275   1109.762   100
   mutate 3410.351 3633.070 4465.0583 3876.6975 4446.0845  34298.910   100
 mutateif 5118.725 5365.126 7241.5727 5637.5520 6290.7795 118874.982   100
person Marijn Stevering    schedule 27.12.2017
comment
{} был первым, что я попробовал, но в моем реальном случае это не сработало, затем я потратил некоторое время на поиск примеров многострочных кодовых блоков в microbenchmark и не смог найти ни одного. При создании моего примера для публикации вопроса я хотел включить это решение в качестве примера того, что я пробовал, и в итоге оно сработало. Я решил, что, поскольку я не нашел ни одного существующего примера в Интернете, его все же стоит опубликовать. - person Marijn Stevering; 27.12.2017