diff --git a/src/common/random.c b/src/common/random.c index fd830a7..31164c1 100644 --- a/src/common/random.c +++ b/src/common/random.c @@ -108,6 +108,40 @@ rand_fill(uint8_t* p_buffer, uint32_t size) return true; } +//------------------------------------------------ +// Fill a buffer with target compression ratio. +// + +bool +comp_fill(uint8_t* p_buffer, uint32_t size, uint32_t compress_percent) +{ + uint64_t* p_write = (uint64_t*)p_buffer; + uint64_t* p_end = (uint64_t*)(p_buffer + size); + // ... relies on size being a multiple of 8, which it will be. + const uint32_t interval_size = 512; // Space out zero runs at this interval + const uint32_t interval_num = size / interval_size; + const uint32_t z_len = (((100 - compress_percent) * interval_size) / 100) / sizeof(uint64_t); + const uint32_t r_len = (interval_size / sizeof(uint64_t)) - z_len; + // ... data must be in interval_size units to achieve target compression ratio + int32_t i, z, r; + + for (i = 0; i < interval_num; i++) { + z = z_len; + while (z--) { + *p_write++ = 0; + } + r = r_len; + while (r--) { + *p_write++ = xorshift128plus(); + } + } + + while (p_write < p_end) { + *p_write++ = xorshift128plus(); + } + + return true; +} //========================================================== // Local helpers. diff --git a/src/common/random.h b/src/common/random.h index b15f7d8..927e494 100644 --- a/src/common/random.h +++ b/src/common/random.h @@ -41,3 +41,4 @@ void rand_seed_thread(); uint32_t rand_32(); uint64_t rand_64(); bool rand_fill(uint8_t* p_buffer, uint32_t size); +bool comp_fill(uint8_t* p_buffer, uint32_t size, uint32_t compress_percent); diff --git a/src/storage/act_storage.c b/src/storage/act_storage.c index 0b60100..05f4b52 100644 --- a/src/storage/act_storage.c +++ b/src/storage/act_storage.c @@ -1047,7 +1047,12 @@ static void write_and_report(trans_req* write_req, uint8_t* buf) { // Salt each record. - rand_fill(buf, write_req->size); + if (g_scfg.compress_percent < 100) { + comp_fill(buf, write_req->size, g_scfg.compress_percent); + } + else { + rand_fill(buf, write_req->size); + } uint64_t raw_start_time = get_ns(); uint64_t stop_time = write_to_device(write_req->dev, write_req->offset, @@ -1070,7 +1075,12 @@ static void write_and_report_large_block(device* dev, uint8_t* buf, uint64_t count) { // Salt the block each time. - rand_fill(buf, g_scfg.large_block_ops_bytes); + if (g_scfg.compress_percent < 100) { + comp_fill(buf, g_scfg.large_block_ops_bytes, g_scfg.compress_percent); + } + else { + rand_fill(buf, g_scfg.large_block_ops_bytes); + } uint64_t offset = random_large_block_offset(dev); uint64_t start_time = get_ns(); diff --git a/src/storage/cfg_storage.c b/src/storage/cfg_storage.c index e16b212..22be0b4 100644 --- a/src/storage/cfg_storage.c +++ b/src/storage/cfg_storage.c @@ -69,6 +69,7 @@ static const char TAG_TOMB_RAIDER_SLEEP_USEC[] = "tomb-raider-sleep-usec"; static const char TAG_MAX_REQS_QUEUED[] = "max-reqs-queued"; static const char TAG_MAX_LAG_SEC[] = "max-lag-sec"; static const char TAG_SCHEDULER_MODE[] = "scheduler-mode"; +static const char TAG_COMPRESS_PERCENT[] = "compress-percent"; #define RBLOCK_SIZE 16 // must be power of 2 @@ -97,7 +98,8 @@ storage_cfg g_scfg = { .defrag_lwm_pct = 50, .max_reqs_queued = 100000, .max_lag_usec = 1000000 * 10, - .scheduler_mode = "noop" + .scheduler_mode = "noop", + .compress_percent = 100 }; @@ -226,6 +228,9 @@ storage_configure(int argc, char* argv[]) else if (strcmp(tag, TAG_SCHEDULER_MODE) == 0) { g_scfg.scheduler_mode = parse_scheduler_mode(); } + else if (strcmp(tag, TAG_COMPRESS_PERCENT) == 0) { + g_scfg.compress_percent = parse_uint32(); + } else { fprintf(stdout, "ERROR: ignoring unknown config item '%s'\n", tag); } @@ -324,6 +329,10 @@ check_configuration() configuration_error(TAG_COMMIT_MIN_BYTES); return false; } + if (g_scfg.compress_percent > 100) { + configuration_error(TAG_COMPRESS_PERCENT); + return false; + } return true; } @@ -495,6 +504,8 @@ echo_configuration() g_scfg.max_lag_usec / 1000000); fprintf(stdout, "%s: %s\n", TAG_SCHEDULER_MODE, g_scfg.scheduler_mode); + fprintf(stdout, "%s: %" PRIu32 "\n", TAG_COMPRESS_PERCENT, + g_scfg.compress_percent); fprintf(stdout, "\nDERIVED CONFIGURATION\n"); diff --git a/src/storage/cfg_storage.h b/src/storage/cfg_storage.h index f66ec9f..db77c57 100644 --- a/src/storage/cfg_storage.h +++ b/src/storage/cfg_storage.h @@ -76,6 +76,7 @@ typedef struct storage_cfg_s { uint32_t write_req_threads; double large_block_reads_per_sec; double large_block_writes_per_sec; + uint32_t compress_percent; } storage_cfg;