Я разрабатываю пакет на R, который является гибридным и использует язык C для оптимизации скорости выполнения некоторых процессов.
Поскольку блок кода в языке C имеет много строк, я Я использую .Call, который отвечает за передачу некоторых параметров с языка R на язык C.
Недавно я понял, что для чтения небольших файлов нет проблем. Однако при чтении больших файлов, таких как файл примера (https://gofile.io/?c=PeQEOx) с двумя столбцами и более чем 80 тысячами строк, объем оперативной памяти (приблизительно 400 МБ) выделяется для выполнения .Call. Эта выделенная память нигде не найдена в R и освобождается только при закрытии программы или перезапуске среды. Это стало проблемой, так как мне иногда нужно запускать пакет для больших файлов несколько раз.
Я искал ответы на этой проблеме на нескольких сайтах и форумах, но не смог найти решение. Кто-нибудь видел эту проблему или знает решение? Я создал этот тест на Linux, но я считаю, что такая же проблема возникает на Windows.
Пример входного файла:
Q0045 YJL166W
Q0045 YDL085W
Q0045 YDR119W-A
Q0045 YPR191W
Q0045 YNR018W
Q0045 Q0105
Q0045 YFR033C
Q0045 YML120C
Q0045 YEL024W
Это код в C:
#include <Rinternals.h>
#include <malloc.h>
int row_number;
SEXP asn;
char buffer[30];
const char ***read_file = NULL;
SEXP test(SEXP S_file) {
int len = length(S_file);
SEXP col1, col2;
col1 = VECTOR_ELT(S_file, 0);
col2 = VECTOR_ELT(S_file, 1);
row_number = length(col1);
read_file = (const char ***) malloc(sizeof(int *)*row_number);
for(int i=0; i<row_number; ++i){
*(read_file+i) = (const char **) malloc(sizeof(int)*row_number);
}
for (int i=0; i<row_number; i++) {
read_file[i][0] = CHAR(STRING_ELT(col1, i));
read_file[i][1] = CHAR(STRING_ELT(col2, i));
}
asn = PROTECT(Rf_allocMatrix(STRSXP,row_number, 2));
for (int i=0; i<row_number; i++) {
for (int n=0; n<2; n++) {
sprintf(buffer, "%s", read_file[i][n]);
SET_STRING_ELT(asn, i, Rf_mkChar(buffer));
}
}
free(read_file);
UNPROTECT(1);
return asn;
}
Это код в R:
file='/home/rafael/Documentos/yeast_08.txt'
file = data.frame(read.table(file, sep = "\t", stringsAsFactors = FALSE))
dyn.load(paste(find.package("example"),"libs", "example.so", sep = "/"))
R = suppressWarnings(suppressMessages(.Call("test",
S_file = file,
PACKAGE = "example")))