Проблемы с производительностью при чтении из сокета - PullRequest
0 голосов
/ 03 апреля 2020

Пакет, который я написал для связи с базой данных BaseX XML (см. https://CRAN.R-project.org/package=RBaseX), кажется стабильным, в прошлом месяце я не видел никаких ошибок. Единственная проблема - производительность. Выполнение этого запроса:

let $words := for $text in collection('IncidentRemarks/IncidentRemarks.csv')/csv/record/INC_RM
  return ft:tokenize($text)
return $words

занимает около 48 мс. Чтение полученных 350000 байт из сокета занимает> 100 секунд.

Я использую эту функцию для чтения из сокета:

str_receive = function(input, output, bin = FALSE) {
  if (missing(input)) input   <- self$get_socket()
  if (missing(output)) output <- raw(0)
  while ((rd <- readBin(input, what = "raw", n =1)) > 0) {
    if (rd == 0xff) rd <- readBin(input, what = "raw", n =1)
    output <- c(output, rd)
  }
  # The 'Full'-method embeds a \0 in the output
  if (!bin) ret <- strip_CR_NUL(output) %>% rawToChar()
  else ret <- output
  return(ret)
  }

Пакет использует R6. Поскольку я еще не нашел хорошего метода для профилирования R6-методов, я использую браузер () для отладки. Это показывает, что while-l oop вызывает задержку. (И я думаю, что именно output <- c(output, rd) является основной проблемой).
Каков наилучший подход для ускорения чтения из сокета?

Самый последний исходный код для этого пакета можно найти в https://github.com/BenEngbers/RBaseX

Бен
PS. Пожалуйста, не говорите, что я должен использовать 'C' или 'CPP'. Мне всегда удавалось избегать этих языков; -)

6 апреля

Я выделил код, который читает из сокета:

socket_reader <- function(socket_in) {
  string_read <- raw(0)
  while ((rd <- readBin(socket_in, what = "raw", n =1)) > 0) {
    if (rd == 0xff) rd <- readBin(socket_in, what = "raw", n =1)
    string_read <- c(string_read, rd)
  }
  return(string_read)
}

И заменил этот код на:

socket_reader <- function(socket_in) {
  string_read <- raw(0)
  CONT <- TRUE
  Buf_Size <- 4096
  while (CONT) {
    read_buffer <- readBin(socket_in, what = "raw", n = Buf_Size)
    if (length(read_buffer) < Buf_Size) CONT <- FALSE
    string_read <- c(string_read, read_buffer)
  }
  string_read <- strip_FF(string_read)
  string_read <- string_read[-(length(string_read))] %>% as.raw()
  return(string_read)
}

Этот код должен быть намного быстрее. Функция strip_FF() удаляет байты \ 0xFF (string) из string_read, поэтому обе версии должны давать одинаковый результат.
Однако между несколькими операциями чтения я должен прочитать (1) байт состояния из соединения. Значение \ 0x00 означает успех, \ 0x01 означает сбой.

Моя новая версия не может прочитать этот байт состояния.

Как я могу прочитать 1 байт из соединения и переместить позицию в соединении?

Ben

1 Ответ

0 голосов
/ 14 апреля 2020

Я предполагал, что функция readLines будет быстрее, чем readBin, и поэтому я попытался применить эту функцию. Кстати, согласно этой статье Читая полный файл с R , это предположение не было оправдано. Теперь я узнал, что readLines можно использовать только для чтения символьных строк, а не для чтения двоичных данных.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...