Пакет, который я написал для связи с базой данных 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