Ответ 1
Бенчмаркинг. Производительность записи и чтения SSD - это сложный бизнес и трудно сделать правильно. Есть много эффектов, которые следует учитывать.
Например, многие методы SSD используют для ускорения скорости передачи данных (интеллектуально), таких как кэширование DRAM. Эти методы могут увеличить скорость записи, особенно в тех случаях, когда идентичный набор данных записывается на диск несколько раз, как в вашем примере. Чтобы избежать этого эффекта, каждая итерация эталонного теста должна записывать уникальный диск на диск.
Также важны размеры блоков операций записи и чтения: размер физического сектора по умолчанию для SSD составляет 4 КБ. Написание небольших блоков затрудняет работу, но с fst
я обнаружил, что запись блоков данных размером более нескольких мегабайт также снижает производительность из - за эффектов кэша процессора. Поскольку fst
записывает данные на диск в относительно небольших фрагментах, он обычно быстрее, чем альтернативы, которые записывают данные в один большой блок.
Чтобы облегчить эту блочную запись на SSD, вы можете изменить свой код:
Rcpp::cppFunction('
#include <fstream>
#include <cstring>
#include <iostream>
#define BLOCKSIZE 262144 // 2^18 bytes per block
long test_blocks(SEXP x, Rcpp::String path) {
char* d = reinterpret_cast<char*>(REAL(x));
std::ofstream outfile;
outfile.open(path.get_cstring(), std::ios::out | std::ios::binary);
long dl = Rf_xlength(x) * 8;
long nr_of_blocks = dl / BLOCKSIZE;
for (long block_nr = 0; block_nr < nr_of_blocks; block_nr++) {
outfile.write(&d[block_nr * BLOCKSIZE], BLOCKSIZE);
}
long remaining_bytes = dl % BLOCKSIZE;
outfile.write(&d[nr_of_blocks * BLOCKSIZE], remaining_bytes);
outfile.close();
return dl;
}
')
Теперь мы можем сравнить методы test
, test_blocks
и fst::write_fst
в одном тесте:
x <- runif(134217728) # 1 gigabyte
df <- data.frame(X = x)
fst::threads_fst(1) # use fst in single threaded mode
microbenchmark::microbenchmark(
test(x, "test.bin"),
test_blocks(x, "test.bin"),
fst::write_fst(df, "test.fst", compress = 0),
times = 10)
#> Unit: seconds
#> expr min lq mean
#> test(x, "test.bin") 1.473615 1.506019 1.590430
#> test_blocks(x, "test.bin") 1.018082 1.062673 1.134956
#> fst::write_fst(df, "test.fst", compress = 0) 1.127446 1.144039 1.249864
#> median uq max neval
#> 1.600055 1.635883 1.765512 10
#> 1.131631 1.204373 1.264220 10
#> 1.261269 1.327304 1.343248 10
Как вы можете видеть, модифицированный метод test_blocks
примерно на 40 процентов быстрее исходного метода и даже немного быстрее, чем fst
пакет. Это ожидается, потому что fst
имеет некоторые накладные расходы при хранении информации о столбцах и таблицах, (возможно) атрибутах, хэшах и информации сжатия.
Обратите внимание, что разница между fst
и вашим первоначальным методом test
намного менее выражена в моей системе, снова демонстрируя проблемы с использованием тестов для оптимизации системы.