# High-level read-throughput benchmarks after = ['bench_file', 'bench_dir', 'bench_wt'] # these are common and can be overridden suite-wide # # note for bench_*_many, file size defaults to CHUNK, and SIZE = sum of # all files # defines.SIZE = '1024*1024' # 1 MiB defines.CHUNK = 64 defines.SEED = 42 # simulated time, in nanoseconds, to run the bench defines.SIM_TIME = '60ULL*60ULL*1000ULL*1000ULL*1000ULL' # 1 hour # simulation size in bytes defines.SIM_SIZE = 0 # set this to true to skip bench warmup defines.SKIP_WARMUP = false # include common bench helpers code = ''' #include "benches/bench_helpers.h" ''' # sequential read throughput [cases.bench_rt_seq] code = ''' lfs3_t lfs3; lfs3_format(&lfs3, LFS3_F_RDWR, CFG) => 0; lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0; if (!SKIP_WARMUP) { BENCH_PAUSE(); int err = bench_helpers_warmup(&lfs3); if (err) { LFS3_ERROR("Bench warmup failed: %d", err); return; } BENCH_RESUME(); } uint32_t prng = SEED; // reset our timer BENCH_SIMRESET(); // create a file to read lfs3_file_t file; lfs3_file_open(&lfs3, &file, "bench_linear", LFS3_O_WRONLY | LFS3_O_CREAT | LFS3_O_EXCL) => 0; for (lfs3_size_t i = 0; i < (SIZE+(CHUNK-1))/CHUNK; i++) { uint8_t wbuf[CHUNK]; for (lfs3_size_t j = 0; j < CHUNK; j++) { wbuf[j] = 'a' + (BENCH_PRNG(&prng) % 26); } lfs3_file_write(&lfs3, &file, wbuf, CHUNK) => CHUNK; // taking too long? if (SIM_TIME && BENCH_SIMTIME() >= (bench_ns_t)SIM_TIME) { return; } } lfs3_file_close(&lfs3, &file) => 0; // reset our timer BENCH_SIMRESET(); // open the file BENCH_START("read"); lfs3_file_open(&lfs3, &file, "bench_linear", LFS3_O_RDONLY) => 0; lfs3_off_t size = 0; uint64_t readed = 0; while (!(SIM_SIZE && readed >= (uint64_t)SIM_SIZE) && !(SIM_TIME && BENCH_SIMTIME() >= (bench_ns_t)SIM_TIME)) { // read from the file uint8_t rbuf[CHUNK]; lfs3_file_read(&lfs3, &file, rbuf, CHUNK) => CHUNK; size += CHUNK; readed += CHUNK; // rewind if we reach the end if (size >= SIZE) { lfs3_file_rewind(&lfs3, &file) => 0; size = 0; } } lfs3_file_close(&lfs3, &file) => 0; // report the amount we managed to read BENCH_STOP("read", readed); lfs3_unmount(&lfs3) => 0; ''' # random read throughput [cases.bench_rt_random] code = ''' lfs3_t lfs3; lfs3_format(&lfs3, LFS3_F_RDWR, CFG) => 0; lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0; if (!SKIP_WARMUP) { BENCH_PAUSE(); int err = bench_helpers_warmup(&lfs3); if (err) { return; } BENCH_RESUME(); } uint32_t prng = SEED; // reset our timer BENCH_SIMRESET(); // create a file to read lfs3_file_t file; lfs3_file_open(&lfs3, &file, "bench_random", LFS3_O_WRONLY | LFS3_O_CREAT | LFS3_O_EXCL) => 0; for (lfs3_size_t i = 0; i < (SIZE+(CHUNK-1))/CHUNK; i++) { uint8_t wbuf[CHUNK]; for (lfs3_size_t j = 0; j < CHUNK; j++) { wbuf[j] = 'a' + (BENCH_PRNG(&prng) % 26); } lfs3_file_write(&lfs3, &file, wbuf, CHUNK) => CHUNK; // taking too long? if (SIM_TIME && BENCH_SIMTIME() >= (bench_ns_t)SIM_TIME) { return; } } lfs3_file_close(&lfs3, &file) => 0; // reset our timer BENCH_SIMRESET(); // open the file BENCH_START("read"); lfs3_file_open(&lfs3, &file, "bench_random", LFS3_O_RDONLY) => 0; uint64_t readed = 0; while (!(SIM_SIZE && readed >= (uint64_t)SIM_SIZE) && !(SIM_TIME && BENCH_SIMTIME() >= (bench_ns_t)SIM_TIME)) { // seek to a random location lfs3_off_t pos = BENCH_PRNG(&prng) % SIZE; lfs3_file_seek(&lfs3, &file, pos, LFS3_SEEK_SET) => pos; // read from the file uint8_t rbuf[CHUNK]; lfs3_ssize_t d = lfs3_file_read(&lfs3, &file, rbuf, CHUNK); assert(d <= CHUNK); readed += CHUNK; } lfs3_file_close(&lfs3, &file) => 0; // report the amount we managed to read BENCH_STOP("read", readed); lfs3_unmount(&lfs3) => 0; ''' # many small file read throughput [cases.bench_rt_many] defines.FILE_SIZE = 'CHUNK' defines.FILE_COUNT = '(SIZE+(FILE_SIZE-1)) / lfs3_max(FILE_SIZE, 1)' code = ''' lfs3_t lfs3; lfs3_format(&lfs3, LFS3_F_RDWR, CFG) => 0; lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0; if (!SKIP_WARMUP) { BENCH_PAUSE(); int err = bench_helpers_warmup(&lfs3); if (err) { return; } BENCH_RESUME(); } uint32_t prng = SEED; // reset our timer BENCH_SIMRESET(); // create files to read for (lfs3_size_t i = 0; i < (SIZE+(CHUNK-1))/CHUNK; i++) { char name[256]; sprintf(name, "bench_%08x", i); lfs3_file_t file; lfs3_file_open(&lfs3, &file, name, LFS3_O_WRONLY | LFS3_O_CREAT | LFS3_O_EXCL) => 0; for (lfs3_size_t i = 0; i < (FILE_SIZE+(CHUNK-1))/CHUNK; i++) { lfs3_ssize_t d = lfs3_min(CHUNK, FILE_SIZE); uint8_t wbuf[CHUNK]; memset(wbuf, 'a'+(BENCH_PRNG(&prng) % 26), d); lfs3_file_write(&lfs3, &file, wbuf, d) => d; // taking too long? if (SIM_TIME && BENCH_SIMTIME() >= (bench_ns_t)SIM_TIME) { return; } } lfs3_file_close(&lfs3, &file) => 0; } // reset our timer BENCH_SIMRESET(); // open the files BENCH_START("read"); uint64_t readed = 0; while (!(SIM_SIZE && readed >= (uint64_t)SIM_SIZE) && !(SIM_TIME && BENCH_SIMTIME() >= (bench_ns_t)SIM_TIME)) { // choose a random filename lfs3_off_t pos = BENCH_PRNG(&prng) % ((SIZE+(CHUNK-1))/CHUNK); char name[256]; sprintf(name, "bench_%08x", pos); uint8_t rbuf[CHUNK]; // read the file // // note file == CHUNK here, the sum of all files should add up // roughly to the benchmark SIZE lfs3_file_t file; lfs3_file_open(&lfs3, &file, name, LFS3_O_RDONLY) => 0; for (lfs3_size_t i = 0; i < (FILE_SIZE+(CHUNK-1))/CHUNK; i++) { lfs3_ssize_t d = lfs3_min(CHUNK, FILE_SIZE); lfs3_file_read(&lfs3, &file, rbuf, d) => d; readed += d; // taking too long? if (SIM_TIME && BENCH_SIMTIME() >= (bench_ns_t)SIM_TIME) { break; } } lfs3_file_close(&lfs3, &file) => 0; } // report the amount we managed to read BENCH_STOP("read", readed); lfs3_unmount(&lfs3) => 0; '''