#include <gtest/gtest.h>
#include <fcntl.h>
#include <chrono>
#include <iostream>
extern "C" {
#include "gr_api.h"
#include "gr_errno.h"
}
#define SIZE_GB 1024 * 1024 * 1024
#define SIZE_MB 1024 * 1024
#define SERVER_ADDR "127.0.0.1:19225"
#define TEST_DIR "performancedir"
#define TEST_FILE "performance_test_file1"
gr_param_t g_gr_param;
gr_file_handle file_handle;
class GRApiPerformanceTest : public ::testing::Test {
protected:
void SetUp() override {
strcpy(g_gr_param.log_home, "./testlog");
g_gr_param.log_level = 255;
g_gr_param.log_backup_file_count = 100;
g_gr_param.log_max_file_size = SIZE_GB;
gr_init(g_gr_param);
int result = gr_create_inst(SERVER_ADDR, &g_inst_handle);
ASSERT_EQ(result, GR_SUCCESS) << "Failed to create instance";
result = gr_vfs_create(g_inst_handle, TEST_DIR, 0);
result = gr_vfs_mount(g_inst_handle, TEST_DIR, &g_vfs_handle);
ASSERT_EQ(result, GR_SUCCESS) << "Failed to mount VFS";
result = gr_file_create(g_vfs_handle, TEST_FILE, NULL);
ASSERT_EQ(result, GR_SUCCESS) << "Failed to create test file";
result = gr_file_open(g_vfs_handle, TEST_FILE, O_RDWR | O_SYNC, &file_handle);
ASSERT_EQ(result, GR_SUCCESS) << "Failed to open test file";
}
void TearDown() override {
gr_file_close(g_vfs_handle, &file_handle, true);
gr_file_delete(g_vfs_handle, TEST_FILE, 0);
gr_vfs_delete(g_inst_handle, TEST_DIR, 0);
}
gr_instance_handle g_inst_handle = NULL;
gr_vfs_handle g_vfs_handle;
gr_file_handle file_handle;
int handle = 0;
};
TEST_F(GRApiPerformanceTest, TestWritePerformance) {
const int data_size = 100 * SIZE_MB;
char *data = new char[data_size];
memset(data, 'A', data_size);
auto start = std::chrono::high_resolution_clock::now();
int result = gr_file_pwrite(g_vfs_handle, &file_handle, data, data_size, 0);
auto end = std::chrono::high_resolution_clock::now();
ASSERT_EQ(result, data_size) << "Failed to write data";
std::chrono::duration<double, std::milli> duration = end - start;
double milliseconds = duration.count();
double speed = data_size / (1024.0 * 1024.0) / (milliseconds / 1000.0);
std::cout << "Write time: " << milliseconds << " milliseconds" << std::endl;
std::cout << "Write speed: " << speed << " MB/s" << std::endl;
delete[] data;
}
TEST_F(GRApiPerformanceTest, TestWritePerformanceWith8KSteps) {
const int step_size = 8 * 1024;
const int total_size = 100 * SIZE_MB;
char *data = new char[step_size];
memset(data, 'B', step_size);
auto total_start = std::chrono::high_resolution_clock::now();
int result = GR_SUCCESS;
double total_latency = 0.0;
int write_count = total_size / step_size;
for (int offset = 0; offset < total_size; offset += step_size) {
auto start = std::chrono::high_resolution_clock::now();
result = gr_file_pwrite(g_vfs_handle, &file_handle, data, step_size, offset);
auto end = std::chrono::high_resolution_clock::now();
ASSERT_EQ(result, step_size) << "Failed to write data at offset " << offset;
std::chrono::duration<double, std::milli> latency = end - start;
total_latency += latency.count();
}
auto total_end = std::chrono::high_resolution_clock::now();
std::chrono::duration<double> total_duration = total_end - total_start;
double total_seconds = total_duration.count();
double speed = total_size / (1024.0 * 1024.0) / total_seconds;
double average_latency = total_latency / write_count;
std::cout << "Total write time with 8KB steps: " << total_seconds << " seconds" << std::endl;
std::cout << "Write speed with 8KB steps: " << speed << " MB/s" << std::endl;
std::cout << "Average latency per 8KB write: " << average_latency << " milliseconds" << std::endl;
delete[] data;
}
int main(int argc, char **argv) {
::testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}