Подтвердить что ты не робот

Скорость gsub против длины шаблона

В последнее время я широко использую gsub, и я заметил, что короткие шаблоны работают быстрее, чем длинные, что неудивительно. Здесь полностью воспроизводимый код:

library(microbenchmark)
set.seed(12345)
n = 0
rpt = seq(20, 1461, 20)
msecFF = numeric(length(rpt))
msecFT = numeric(length(rpt))
inp = rep("aaaaaaaaaa",15000)

for (i in rpt) {
  n = n + 1
  print(n)
  patt = paste(rep("a", rpt[n]), collapse = "")
  #time = microbenchmark(func(count[1:10000,12], patt, "b"), times = 10)
  timeFF = microbenchmark(gsub(patt, "b", inp, fixed=F), times = 10)
  msecFF[n] = mean(timeFF$time)/1000000.

  timeFT = microbenchmark(gsub(patt, "b", inp, fixed=T), times = 10)
  msecFT[n] = mean(timeFT$time)/1000000.
}

library(ggplot2)
library(grid)
library(gridExtra)

axis(1,at=seq(0,1000,200),labels=T)

p1 = qplot(rpt, msecFT, xlab="pattern length, characters", ylab="time, msec",main="fixed = TRUE" )
p2 = qplot(rpt, msecFF, xlab="pattern length, characters", ylab="time, msec",main="fixed = FALSE")
grid.arrange(p1, p2, nrow = 2)

Как вы видите, я ищу шаблон, содержащий a реплицированный rpt[n] раз. Наклон положительный, как и ожидалось. Тем не менее, я заметил излом с 300 символами с fixed=T и 600 символами с fixed=F, а затем наклон кажется примерно таким же, как и раньше (см. График ниже). Я полагаю, это связано с памятью, размером объекта и т.д. Я также заметил, что самый длинный допустимый pattern - это 1463 символа с размером объекта 1552 байта.

Может кто-нибудь объяснить кивок лучше и почему у 300 и 600 символов?

gsub speed in milliseconds with fixed turned on/off as a function of pattern length in characters

Добавлено: стоит упомянуть, что большинство моих паттернов имеют длину 5-10 символов, что дает мне мои реальные данные (а не макет inp в приведенном выше примере) следующее время.

gsub, fixed = TRUE: ~50 msec per one pattern
gsub, fixed = FALSE: ~190 msec per one pattern
stringi, fixed = FALSE: ~55 msec per one pattern
gsub, fixed = FALSE, perl = TRUE: ~95 msec per one pattern

(у меня есть 4k-шаблоны, поэтому общее время моего модуля составляет примерно 200 секунд, что составляет ровно 0,05 х 4000 с gsub и fixed = TRUE. Это самый быстрый метод для моих данных и шаблонов)

Real data timing

4b9b3361

Ответ 1

Кинки могут быть связаны с битами, необходимыми для хранения паттернов этой длины.

Существует еще одно решение, которое масштабируется намного лучше, используйте оператор повторения {}, чтобы указать, сколько повторений вы хотите найти. Чтобы найти более 255 (8-битное целочисленное значение max), вам нужно указать perl = TRUE.

patt2 <- paste0('a{',rpt[n],'}')
timeRF <- microbenchmark(gsub(patt2, "b", inp, perl = T), times = 10)

Я получаю скорость около 2,1 мс за поиск без штрафа за длину шаблона. Это примерно в 8 раз быстрее фиксированного = FALSE для небольших длин шаблонов и примерно на 60x быстрее для больших длин шаблонов.