raid: add cold cache test

Signed-off-by: Pablo de Lara <pablo.de.lara.guarch@intel.com>
This commit is contained in:
Pablo de Lara
2025-07-07 10:42:22 +00:00
committed by Marcel Cornu
parent 55e25f7aa2
commit f2883f24fd

View File

@@ -50,6 +50,8 @@
#define DEFAULT_SOURCES 10 #define DEFAULT_SOURCES 10
#define DEFAULT_TEST_LEN 8 * 1024 #define DEFAULT_TEST_LEN 8 * 1024
#define COLD_CACHE_TEST_MEM (1024 * 1024 * 1024)
// Define RAID function types // Define RAID function types
typedef enum { typedef enum {
// XOR function // XOR function
@@ -60,8 +62,25 @@ typedef enum {
RAID_ALL = 2 RAID_ALL = 2
} raid_type_t; } raid_type_t;
// Function pointer type for RAID functions
typedef int (*raid_func_t)(int vects, int len, void **array);
// Helper function to get buffer count for a specific RAID type
static int
get_buffer_count(const raid_type_t type, const int sources)
{
switch (type) {
case XOR_GEN:
return sources + 1; // +1 for destination buffer
case PQ_GEN:
default:
return sources + 2; // +2 for P and Q buffers
}
}
void void
run_benchmark(void *buffs[], size_t len, int sources, raid_type_t type, int csv_output); run_benchmark(void *buffs[], const size_t len, const int sources, const raid_type_t type,
const int csv_output, const int use_cold_cache);
void void
print_help(void); print_help(void);
void void
@@ -72,55 +91,119 @@ size_t
parse_size_value(const char *size_str); parse_size_value(const char *size_str);
static void static void
run_raid_type_range(raid_type_t type, void *buffs[], size_t min_len, size_t max_len, run_raid_type_range(const raid_type_t type, void *buffs[], const size_t min_len,
int is_multiplicative, size_t abs_step, int sources, int csv_output); const size_t max_len, const int is_multiplicative, const size_t abs_step,
const int sources, const int csv_output, const int use_cold_cache);
static void static void
run_raid_type_size_list(raid_type_t type, void *buffs[], size_t *size_list, int size_count, run_raid_type_size_list(const raid_type_t type, void *buffs[], const size_t *size_list,
int sources, int csv_output); const int size_count, const int sources, const int csv_output,
const int use_cold_cache);
void void
benchmark_raid_type_range(raid_type_t raid_type, void *buffs[], size_t min_len, size_t max_len, benchmark_raid_type_range(const raid_type_t raid_type, void *buffs[], const size_t min_len,
ssize_t step_len, int sources, int csv_output); const size_t max_len, const ssize_t step_len, const int sources,
const int csv_output, const int use_cold_cache);
void void
benchmark_raid_type_size_list(raid_type_t raid_type, void *buffs[], size_t *size_list, benchmark_raid_type_size_list(const raid_type_t raid_type, void *buffs[], const size_t *size_list,
int size_count, int sources, int csv_output); const int size_count, const int sources, const int csv_output,
const int use_cold_cache);
// Function to run a specific RAID benchmark // Function to run a specific RAID benchmark
// len is the block size for each source and destination buffer, in bytes
void void
run_benchmark(void *buffs[], size_t len, int sources, raid_type_t type, int csv_output) run_benchmark(void *buffs[], const size_t len, const int num_sources_dest, const raid_type_t type,
const int csv_output, const int use_cold_cache)
{ {
struct perf start; struct perf start;
const char *raid_type_str = ""; const char *raid_type_str = "";
raid_func_t raid_func = NULL;
// Set up function pointer and type string based on RAID type
switch (type) { switch (type) {
// XOR function
case XOR_GEN: case XOR_GEN:
raid_type_str = "xor_gen"; raid_type_str = "xor_gen";
BENCHMARK(&start, BENCHMARK_TIME, xor_gen(sources, len, buffs)); raid_func = xor_gen;
break; break;
// P+Q function
case PQ_GEN: case PQ_GEN:
raid_type_str = "pq_gen"; raid_type_str = "pq_gen";
BENCHMARK(&start, BENCHMARK_TIME, pq_gen(sources, len, buffs)); raid_func = pq_gen;
break; break;
default: default:
printf("Invalid RAID function type\n"); fprintf(stderr, "Invalid RAID function type\n");
return; exit(1);
}
// Create list of random buffer addresses within the large memory space for cold cache tests
if (use_cold_cache) {
const size_t buffer_size_each =
COLD_CACHE_TEST_MEM / (num_sources_dest + 2); // +2 for max buffers needed
const size_t num_buffer_sets = buffer_size_each / len;
if (num_buffer_sets == 0) {
fprintf(stderr, "Buffer size too large for cold cache test\n");
exit(1);
}
void ***buffer_set_list = (void ***) malloc(num_buffer_sets * sizeof(void **));
if (!buffer_set_list) {
fprintf(stderr, "Failed to allocate memory for cold cache buffer list\n");
exit(1);
}
// For each buffer set, create pointers to random offsets within the allocated
// memory
for (size_t i = 0; i < num_buffer_sets; i++) {
buffer_set_list[i] = (void **) malloc(num_sources_dest * sizeof(void *));
if (!buffer_set_list[i]) {
fprintf(stderr,
"Failed to allocate memory for cold cache buffer set %zu\n",
i);
// Clean up previously allocated sets
for (size_t j = 0; j < i; j++)
free(buffer_set_list[j]);
free(buffer_set_list);
exit(1);
}
// Calculate random offset for this buffer set, ensuring we don't exceed
// buffer bounds
const size_t offset = len * (rand() % num_buffer_sets);
for (int j = 0; j < num_sources_dest; j++)
buffer_set_list[i][j] = (uint8_t *) buffs[j] + offset;
}
size_t current_buffer_idx = 0;
BENCHMARK_COLD(
&start, BENCHMARK_TIME,
current_buffer_idx = (current_buffer_idx + 1) % num_buffer_sets,
raid_func(num_sources_dest, len, buffer_set_list[current_buffer_idx]));
for (size_t i = 0; i < num_buffer_sets; i++)
free(buffer_set_list[i]);
free(buffer_set_list);
} else {
BENCHMARK(&start, BENCHMARK_TIME, raid_func(num_sources_dest, len, buffs));
} }
if (csv_output) { if (csv_output) {
#ifdef USE_RDTSC
// When USE_RDTSC is defined, report total cycles per buffer
const double cycles = (double) get_base_elapsed(&start);
const double cycles_per_buffer = cycles / (double) start.iterations;
printf("%s,%zu,%d,%.0f\n", raid_type_str, len, num_sources_dest, cycles_per_buffer);
#else
// Calculate throughput in MB/s // Calculate throughput in MB/s
double time_elapsed = get_time_elapsed(&start); const double time_elapsed = get_time_elapsed(&start);
long long total_sources = start.iterations * sources; const long long total_sources_dest = start.iterations * num_sources_dest;
long long total_units = total_sources * (long long) len; const long long total_units = total_sources_dest * (long long) len;
double throughput = ((double) total_units) / (1000000 * time_elapsed); const double throughput = ((double) total_units) / (1000000 * time_elapsed);
printf("%s,%zu,%d,%.2f\n", raid_type_str, len, num_sources_dest, throughput);
printf("%s,%zu,%d,%.2f\n", raid_type_str, len, sources, throughput); #endif
} else { } else {
printf("%s: ", raid_type_str); printf("%s: ", raid_type_str);
perf_print(start, (long long) len * sources); perf_print(start, (long long) len * num_sources_dest);
} }
} }
@@ -151,6 +234,7 @@ print_help(void)
printf(" Example: --sizes 1024,4096,8192,16384\n"); printf(" Example: --sizes 1024,4096,8192,16384\n");
printf(" Size values can include K (KB) or M (MB) suffix\n"); printf(" Size values can include K (KB) or M (MB) suffix\n");
printf(" -c, --csv Output results in CSV format\n"); printf(" -c, --csv Output results in CSV format\n");
printf(" --cold Use cold cache for benchmarks (buffer not in cache)\n");
} }
void void
@@ -173,12 +257,11 @@ parse_raid_type(const char *type_str)
// Try as integer first // Try as integer first
char *endptr; char *endptr;
long val = strtol(type_str, &endptr, 10); const long val = strtol(type_str, &endptr, 10);
// If the entire string was parsed as an integer and it's within range // If the entire string was parsed as an integer and it's within range
if (*type_str != '\0' && *endptr == '\0' && val >= 0 && val <= RAID_ALL) { if (*type_str != '\0' && *endptr == '\0' && val >= 0 && val <= RAID_ALL)
return (raid_type_t) val; return (raid_type_t) val;
}
// XOR function // XOR function
if (strcasecmp(type_str, "xor_gen") == 0) if (strcasecmp(type_str, "xor_gen") == 0)
@@ -203,13 +286,14 @@ parse_size_value(const char *size_str)
size_t size_val; size_t size_val;
char *endptr; char *endptr;
size_t multiplier = 1; size_t multiplier = 1;
char *str_copy = strdup(size_str); char *const str_copy = strdup(size_str); // Check for size suffixes (K for KB, M for MB)
if (!str_copy)
return 0;
// Check for size suffixes (K for KB, M for MB) const int len = strlen(str_copy);
int len = strlen(str_copy);
if (len > 0) { if (len > 0) {
// Convert to uppercase for case-insensitive comparison // Convert to uppercase for case-insensitive comparison
char last_char = toupper(str_copy[len - 1]); const char last_char = toupper(str_copy[len - 1]);
if (last_char == 'K') { if (last_char == 'K') {
multiplier = 1024; multiplier = 1024;
@@ -236,14 +320,15 @@ parse_size_value(const char *size_str)
} }
#define MAX_SIZE_COUNT 32 // Maximum number of buffer sizes that can be specified #define MAX_SIZE_COUNT 32 // Maximum number of buffer sizes that can be specified
#define MAX_BUFFERS 20 // Maximum number of source buffers #define MAX_SRC_BUFS 20 // Maximum number of source buffers
int int
main(int argc, char *argv[]) main(int argc, char *argv[])
{ {
void **buffs; void **buffs;
raid_type_t raid_type = RAID_ALL; raid_type_t raid_type = RAID_ALL;
int csv_output = 0; // Flag for CSV output mode int csv_output = 0; // Flag for CSV output mode
int use_cold_cache = 0; // Flag for cold cache mode
size_t test_len = DEFAULT_TEST_LEN; size_t test_len = DEFAULT_TEST_LEN;
int use_range = 0; int use_range = 0;
size_t min_len = 0, max_len = 0; size_t min_len = 0, max_len = 0;
@@ -271,8 +356,9 @@ main(int argc, char *argv[])
// Check if value is outside valid range for individual RAID types // Check if value is outside valid range for individual RAID types
// or group types // or group types
if (raid_type > RAID_ALL) { if (raid_type > RAID_ALL) {
printf("Invalid RAID type: '%s'. Using default (all).\n", fprintf(stderr,
argv[i + 1]); "Invalid RAID type: '%s'. Using default (all).\n",
argv[i + 1]);
raid_type = RAID_ALL; raid_type = RAID_ALL;
} }
i++; // Skip the argument value in the next iteration i++; // Skip the argument value in the next iteration
@@ -288,19 +374,21 @@ main(int argc, char *argv[])
if (i + 1 < argc && argv[i + 1][0] != '-') { if (i + 1 < argc && argv[i + 1][0] != '-') {
sources = atoi(argv[i + 1]); sources = atoi(argv[i + 1]);
if (sources <= 0) { if (sources <= 0) {
printf("Invalid number of sources: %s. Using default " fprintf(stderr,
"(%d).\n", "Invalid number of sources: %s. Using default "
argv[i + 1], DEFAULT_SOURCES); "(%d).\n",
argv[i + 1], DEFAULT_SOURCES);
sources = DEFAULT_SOURCES; sources = DEFAULT_SOURCES;
} else if (sources > MAX_BUFFERS) { } else if (sources > MAX_SRC_BUFS) {
printf("Number of sources too large: %d. Using maximum " fprintf(stderr,
"(%d).\n", "Number of sources too large: %d. Using maximum "
sources, MAX_BUFFERS); "(%d).\n",
sources = MAX_BUFFERS; sources, MAX_SRC_BUFS);
sources = MAX_SRC_BUFS;
} }
i++; // Skip the argument value in the next iteration i++; // Skip the argument value in the next iteration
} else { } else {
printf("Option --sources requires an argument.\n"); fprintf(stderr, "Option --sources requires an argument.\n");
print_help(); print_help();
return 0; return 0;
} }
@@ -311,9 +399,12 @@ main(int argc, char *argv[])
if (i + 1 < argc && argv[i + 1][0] != '-') { if (i + 1 < argc && argv[i + 1][0] != '-') {
// Range specified, parse it // Range specified, parse it
char *range_arg = strdup(argv[i + 1]); char *range_arg = strdup(argv[i + 1]);
char *min_str = strtok(range_arg, ":"); char *const min_str = strtok(range_arg, ":");
char *step_str = strtok(NULL, ":"); char *const step_str = strtok(NULL, ":");
char *max_str = strtok(NULL, ":"); char *const max_str = strtok(NULL, ":");
if (!range_arg)
return 1;
if (min_str && step_str && max_str) { if (min_str && step_str && max_str) {
min_len = parse_size_value(min_str); min_len = parse_size_value(min_str);
@@ -323,12 +414,11 @@ main(int argc, char *argv[])
int step_is_multiplicative = 0; int step_is_multiplicative = 0;
if (step_str[0] == '*') { if (step_str[0] == '*') {
step_is_multiplicative = 1; step_is_multiplicative = 1;
if (strlen(step_str) > 1) { if (strlen(step_str) > 1)
step_len = parse_size_value( step_len = parse_size_value(
step_str + 1); // Skip the '*' step_str + 1); // Skip the '*'
} else { else
step_len = 0; // Invalid step step_len = 0; // Invalid step
}
} else { } else {
step_len = parse_size_value(step_str); step_len = parse_size_value(step_str);
} }
@@ -346,15 +436,17 @@ main(int argc, char *argv[])
step_len = -step_len; step_len = -step_len;
} }
} else { } else {
printf("Invalid range values. Ensure MIN > 0, MAX " fprintf(stderr,
">= MIN, " "Invalid range values. Ensure MIN > 0, MAX "
"and STEP > 0.\n"); ">= MIN, "
"and STEP > 0.\n");
free(range_arg); free(range_arg);
return 1; return 1;
} }
} else { } else {
printf("Invalid range format. Use MIN:STEP:MAX (e.g., " fprintf(stderr,
"1024:1024:16384 or 1024:*2:16384)\n"); "Invalid range format. Use MIN:STEP:MAX (e.g., "
"1024:1024:16384 or 1024:*2:16384)\n");
free(range_arg); free(range_arg);
return 1; return 1;
} }
@@ -362,7 +454,7 @@ main(int argc, char *argv[])
free(range_arg); free(range_arg);
i++; // Skip the argument value in the next iteration i++; // Skip the argument value in the next iteration
} else { } else {
printf("Option -r requires an argument.\n"); fprintf(stderr, "Option -r requires an argument.\n");
print_help(); print_help();
return 0; return 0;
} }
@@ -381,20 +473,22 @@ main(int argc, char *argv[])
if (size_val > 0) { if (size_val > 0) {
if (prev_size > 0 && size_val <= prev_size) { if (prev_size > 0 && size_val <= prev_size) {
printf("Invalid size value: %zu. Sizes " fprintf(stderr,
"must be in " "Invalid size value: %zu. Sizes "
"ascending order.\n", "must be in "
size_val); "ascending order.\n",
size_val);
free(sizes_arg); free(sizes_arg);
return 1; return 1;
} }
prev_size = size_val; prev_size = size_val;
} else { } else {
printf("Invalid size value: '%s'. Sizes must be " fprintf(stderr,
"positive " "Invalid size value: '%s'. Sizes must be "
"integers with optional K (KB) or M (MB) " "positive "
"suffix.\n", "integers with optional K (KB) or M (MB) "
size_str); "suffix.\n",
size_str);
free(sizes_arg); free(sizes_arg);
return 1; return 1;
} }
@@ -424,7 +518,7 @@ main(int argc, char *argv[])
free(sizes_arg); free(sizes_arg);
i++; // Skip the argument value in the next iteration i++; // Skip the argument value in the next iteration
} else { } else {
printf("Option -s requires an argument.\n"); fprintf(stderr, "Option -s requires an argument.\n");
print_help(); print_help();
return 0; return 0;
} }
@@ -435,9 +529,15 @@ main(int argc, char *argv[])
csv_output = 1; csv_output = 1;
} }
// Cold cache option
else if (strcmp(argv[i], "--cold") == 0) {
use_cold_cache = 1;
printf("Cold cache option enabled\n");
}
// Unknown option // Unknown option
else if (argv[i][0] == '-') { else if (argv[i][0] == '-') {
printf("Unknown option: %s\n", argv[i]); fprintf(stderr, "Unknown option: %s\n", argv[i]);
print_help(); print_help();
return 1; return 1;
} }
@@ -446,28 +546,38 @@ main(int argc, char *argv[])
if (!csv_output) { if (!csv_output) {
printf("RAID Functions Performance Benchmark\n"); printf("RAID Functions Performance Benchmark\n");
} else { } else {
#ifdef USE_RDTSC
printf("raid_type,buffer_size,sources+dest,cycles\n");
#else
printf("raid_type,buffer_size,sources+dest,throughput\n"); printf("raid_type,buffer_size,sources+dest,throughput\n");
#endif
} }
// For XOR and P+Q, we need sources + 1 or sources + 2 buffers // For XOR and P+Q, we need sources + 1 or sources + 2 buffers
int max_needed_buffs = sources + 2; const int max_needed_buffs =
if (max_needed_buffs > MAX_BUFFERS) { get_buffer_count(PQ_GEN, sources); // PQ_GEN needs the most buffers
printf("Error: Source count too large for buffer allocation\n"); if (max_needed_buffs > MAX_SRC_BUFS) {
fprintf(stderr, "Error: Source count too large for buffer allocation\n");
return 1; return 1;
} }
// For cold cache, we need larger buffers to accommodate the full memory space
if (use_cold_cache)
test_len = COLD_CACHE_TEST_MEM / max_needed_buffs;
// Allocate buffer pointers // Allocate buffer pointers
buffs = (void **) malloc(sizeof(void *) * max_needed_buffs); buffs = (void **) malloc(sizeof(void *) * max_needed_buffs);
if (!buffs) { if (!buffs) {
printf("Error: Failed to allocate buffer pointers\n"); fprintf(stderr, "Error: Failed to allocate buffer pointers\n");
return 1; return 1;
} }
srand(20250707);
// Allocate the actual buffers // Allocate the actual buffers
for (int i = 0; i < max_needed_buffs; i++) { for (int i = 0; i < max_needed_buffs; i++) {
int ret = posix_memalign(&buffs[i], 64, test_len); int ret = posix_memalign(&buffs[i], 64, test_len);
if (ret) { if (ret) {
printf("Error: Failed to allocate buffer memory\n"); fprintf(stderr, "Error: Failed to allocate buffer memory\n");
// Free previously allocated buffers // Free previously allocated buffers
for (int j = 0; j < i; j++) { for (int j = 0; j < i; j++) {
aligned_free(buffs[j]); aligned_free(buffs[j]);
@@ -475,8 +585,9 @@ main(int argc, char *argv[])
free(buffs); free(buffs);
return 1; return 1;
} }
// Initialize buffer with zeros // Initialize buffer with random data
memset(buffs[i], 0, test_len); for (size_t j = 0; j < test_len; j++)
((uint8_t *) buffs[i])[j] = rand() & 0xFF;
} }
// Process according to chosen RAID type and size options // Process according to chosen RAID type and size options
@@ -489,13 +600,13 @@ main(int argc, char *argv[])
// Call the benchmark function for specific type with range parameters // Call the benchmark function for specific type with range parameters
benchmark_raid_type_range(raid_type, buffs, min_len, max_len, step_len, sources, benchmark_raid_type_range(raid_type, buffs, min_len, max_len, step_len, sources,
csv_output); csv_output, use_cold_cache);
} else { } else {
// Use list of specific sizes // Use list of specific sizes
// Call the benchmark function for specific type with size list parameters // Call the benchmark function for specific type with size list parameters
benchmark_raid_type_size_list(raid_type, buffs, size_list, size_count, sources, benchmark_raid_type_size_list(raid_type, buffs, size_list, size_count, sources,
csv_output); csv_output, use_cold_cache);
} }
if (!csv_output) { if (!csv_output) {
@@ -513,31 +624,25 @@ main(int argc, char *argv[])
/* Helper function to process a specific RAID type for benchmark_raid_type_range */ /* Helper function to process a specific RAID type for benchmark_raid_type_range */
static void static void
run_raid_type_range(raid_type_t type, void *buffs[], size_t min_len, size_t max_len, run_raid_type_range(const raid_type_t type, void *buffs[], const size_t min_len,
int is_multiplicative, size_t abs_step, int sources, int csv_output) const size_t max_len, const int is_multiplicative, const size_t abs_step,
const int sources, const int csv_output, const int use_cold_cache)
{ {
const char *type_names[] = { "XOR Generation", "P+Q Generation" }; const char *type_names[] = { "XOR Generation", "P+Q Generation" };
size_t len; size_t len;
int buffer_count; const int buffer_count = get_buffer_count(type, sources);
if (!csv_output && type < RAID_ALL) { if (!csv_output && type < RAID_ALL) {
printf("\n%s (%d sources):\n", type_names[type], sources); printf("\n%s (%d sources):\n", type_names[type], sources);
} }
/* We need to adjust the buffer count based on function type */
buffer_count = sources;
if (type == XOR_GEN) {
buffer_count = sources + 1; /* +1 for destination buffer */
} else if (type == PQ_GEN) {
buffer_count = sources + 2; /* +2 for P and Q buffers */
}
for (len = min_len; len <= max_len;) { for (len = min_len; len <= max_len;) {
if (!csv_output) { if (!csv_output) {
printf("\n Buffer size: %zu bytes\n", len); printf("\n Buffer size: %zu bytes\n", len);
} }
run_benchmark(buffs, len, buffer_count, type, csv_output); run_benchmark(buffs, len, buffer_count, type, csv_output, use_cold_cache);
/* Update length based on step type */ /* Update length based on step type */
if (is_multiplicative) { if (is_multiplicative) {
@@ -550,11 +655,12 @@ run_raid_type_range(raid_type_t type, void *buffs[], size_t min_len, size_t max_
/* Helper function to run benchmarks for a specific RAID type with range of sizes */ /* Helper function to run benchmarks for a specific RAID type with range of sizes */
void void
benchmark_raid_type_range(raid_type_t raid_type, void *buffs[], size_t min_len, size_t max_len, benchmark_raid_type_range(const raid_type_t raid_type, void *buffs[], const size_t min_len,
ssize_t step_len, int sources, int csv_output) const size_t max_len, const ssize_t step_len, const int sources,
const int csv_output, const int use_cold_cache)
{ {
int is_multiplicative = (step_len < 0); const int is_multiplicative = (step_len < 0);
size_t abs_step = is_multiplicative ? -step_len : step_len; const size_t abs_step = is_multiplicative ? -step_len : step_len;
/* Process according to the chosen RAID type */ /* Process according to the chosen RAID type */
if (raid_type == RAID_ALL) { if (raid_type == RAID_ALL) {
@@ -562,26 +668,27 @@ benchmark_raid_type_range(raid_type_t raid_type, void *buffs[], size_t min_len,
if (!csv_output) if (!csv_output)
printf("\n=========== XOR FUNCTION ===========\n"); printf("\n=========== XOR FUNCTION ===========\n");
run_raid_type_range(XOR_GEN, buffs, min_len, max_len, is_multiplicative, abs_step, run_raid_type_range(XOR_GEN, buffs, min_len, max_len, is_multiplicative, abs_step,
sources, csv_output); sources, csv_output, use_cold_cache);
if (!csv_output) if (!csv_output)
printf("\n=========== P+Q FUNCTION ===========\n"); printf("\n=========== P+Q FUNCTION ===========\n");
run_raid_type_range(PQ_GEN, buffs, min_len, max_len, is_multiplicative, abs_step, run_raid_type_range(PQ_GEN, buffs, min_len, max_len, is_multiplicative, abs_step,
sources, csv_output); sources, csv_output, use_cold_cache);
} else { } else {
/* Run just the specific RAID type */ /* Run just the specific RAID type */
run_raid_type_range(raid_type, buffs, min_len, max_len, is_multiplicative, abs_step, run_raid_type_range(raid_type, buffs, min_len, max_len, is_multiplicative, abs_step,
sources, csv_output); sources, csv_output, use_cold_cache);
} }
} }
/* Helper function to process a specific RAID type for benchmark_raid_type_size_list */ /* Helper function to process a specific RAID type for benchmark_raid_type_size_list */
static void static void
run_raid_type_size_list(raid_type_t type, void *buffs[], size_t *size_list, int size_count, run_raid_type_size_list(const raid_type_t type, void *buffs[], const size_t *size_list,
int sources, int csv_output) const int size_count, const int sources, const int csv_output,
const int use_cold_cache)
{ {
const char *type_names[] = { "XOR Generation", "P+Q Generation" }; const char *type_names[] = { "XOR Generation", "P+Q Generation" };
int buffer_count; const int buffer_count = get_buffer_count(type, sources);
int i; int i;
size_t len; size_t len;
@@ -589,42 +696,37 @@ run_raid_type_size_list(raid_type_t type, void *buffs[], size_t *size_list, int
printf("\n%s (%d sources):\n", type_names[type], sources); printf("\n%s (%d sources):\n", type_names[type], sources);
} }
/* We need to adjust the buffer count based on function type */
buffer_count = sources;
if (type == XOR_GEN) {
buffer_count = sources + 1; /* +1 for destination buffer */
} else if (type == PQ_GEN) {
buffer_count = sources + 2; /* +2 for P and Q buffers */
}
for (i = 0; i < size_count; i++) { for (i = 0; i < size_count; i++) {
len = size_list[i]; len = size_list[i];
if (!csv_output) { if (!csv_output) {
printf("\n Buffer size: %zu bytes\n", len); printf("\n Buffer size: %zu bytes\n", len);
} }
run_benchmark(buffs, len, buffer_count, type, csv_output); run_benchmark(buffs, len, buffer_count, type, csv_output, use_cold_cache);
} }
} }
/* Helper function to run benchmarks for a specific RAID type with list of sizes */ /* Helper function to run benchmarks for a specific RAID type with list of sizes */
void void
benchmark_raid_type_size_list(raid_type_t raid_type, void *buffs[], size_t *size_list, benchmark_raid_type_size_list(const raid_type_t raid_type, void *buffs[], const size_t *size_list,
int size_count, int sources, int csv_output) const int size_count, const int sources, const int csv_output,
const int use_cold_cache)
{ {
/* Process according to the chosen RAID type */ /* Process according to the chosen RAID type */
if (raid_type == RAID_ALL) { if (raid_type == RAID_ALL) {
/* Run all RAID types */ /* Run all RAID types */
if (!csv_output) if (!csv_output)
printf("\n=========== XOR FUNCTION ===========\n"); printf("\n=========== XOR FUNCTION ===========\n");
run_raid_type_size_list(XOR_GEN, buffs, size_list, size_count, sources, csv_output); run_raid_type_size_list(XOR_GEN, buffs, size_list, size_count, sources, csv_output,
use_cold_cache);
if (!csv_output) if (!csv_output)
printf("\n=========== P+Q FUNCTION ===========\n"); printf("\n=========== P+Q FUNCTION ===========\n");
run_raid_type_size_list(PQ_GEN, buffs, size_list, size_count, sources, csv_output); run_raid_type_size_list(PQ_GEN, buffs, size_list, size_count, sources, csv_output,
use_cold_cache);
} else { } else {
/* Run just the specific RAID type */ /* Run just the specific RAID type */
run_raid_type_size_list(raid_type, buffs, size_list, size_count, sources, run_raid_type_size_list(raid_type, buffs, size_list, size_count, sources,
csv_output); csv_output, use_cold_cache);
} }
} }