#include "crdt.hpp"
#include <chrono>
#include <iostream>
#include <random>
#include <string>
#include <vector>
using RecordId = std::string;
using FieldValue = std::string;
using MyCRDT = CRDT<RecordId, FieldValue>;
class CrdtBenchmark {
public:
CrdtBenchmark(CrdtNodeId node1_id, CrdtNodeId node2_id)
: node1(node1_id), node2(node2_id), last_db_version_node1(0), last_db_version_node2(0) {}
void runBenchmark() {
std::cout << "Starting CRDT Benchmark..." << std::endl;
insertRecords(1000);
updateRecords(1000, std::chrono::seconds(5));
deleteRecords(500);
synchronizeNodes();
std::cout << "CRDT Benchmark completed." << std::endl;
}
private:
MyCRDT node1;
MyCRDT node2;
uint64_t last_db_version_node1;
uint64_t last_db_version_node2;
std::vector<RecordId> record_ids;
std::string generate_random_string(size_t length) {
const char charset[] = "0123456789"
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
"abcdefghijklmnopqrstuvwxyz";
const size_t max_index = sizeof(charset) - 1;
std::default_random_engine rng(std::random_device{}());
std::uniform_int_distribution<> dist(0, max_index - 1);
std::string str(length, 0);
for (size_t i = 0; i < length; ++i) {
str[i] = charset[dist(rng)];
}
return str;
}
void insertRecords(size_t count) {
std::cout << "Inserting " << count << " records..." << std::endl;
auto start = std::chrono::high_resolution_clock::now();
for (size_t i = 0; i < count; ++i) {
RecordId rid = "record_" + std::to_string(i) + "_" + generate_random_string(8);
record_ids.push_back(rid);
node1.insert_or_update(rid, std::make_pair("field1", "value1_" + std::to_string(i)),
std::make_pair("field2", "value2_" + std::to_string(i)));
}
auto end = std::chrono::high_resolution_clock::now();
auto duration_ms = std::chrono::duration_cast<std::chrono::milliseconds>(end - start).count();
std::cout << "Inserted " << count << " records in " << duration_ms << " ms." << std::endl;
}
void updateRecords(size_t count, std::chrono::seconds duration) {
std::cout << "Updating records for " << duration.count() << " seconds..." << std::endl;
auto start = std::chrono::high_resolution_clock::now();
size_t updates = 0;
std::default_random_engine rng(std::random_device{}());
std::uniform_int_distribution<size_t> dist(0, record_ids.size() - 1);
std::uniform_int_distribution<int> field_dist(1, 2);
while (std::chrono::high_resolution_clock::now() - start < duration) {
size_t index = dist(rng);
RecordId rid = record_ids[index];
int field_num = field_dist(rng);
node1.insert_or_update(rid,
std::make_pair("field" + std::to_string(field_num), "updated_value_" + std::to_string(updates)));
updates++;
}
auto end = std::chrono::high_resolution_clock::now();
auto elapsed_ms = std::chrono::duration_cast<std::chrono::milliseconds>(end - start).count();
std::cout << "Performed " << updates << " updates in " << elapsed_ms << " ms." << std::endl;
}
void deleteRecords(size_t count) {
std::cout << "Deleting " << count << " records..." << std::endl;
auto start = std::chrono::high_resolution_clock::now();
size_t deletions = 0;
for (size_t i = 0; i < count && i < record_ids.size(); ++i) {
RecordId rid = record_ids[i];
node1.delete_record(rid);
deletions++;
}
auto end = std::chrono::high_resolution_clock::now();
auto duration_ms = std::chrono::duration_cast<std::chrono::milliseconds>(end - start).count();
std::cout << "Deleted " << deletions << " records in " << duration_ms << " ms." << std::endl;
}
void synchronizeNodes() {
std::cout << "Synchronizing node1 to node2..." << std::endl;
auto start = std::chrono::high_resolution_clock::now();
sync_nodes(node1, node2, last_db_version_node1);
sync_nodes(node2, node1, last_db_version_node2);
auto end = std::chrono::high_resolution_clock::now();
auto duration_ms = std::chrono::duration_cast<std::chrono::milliseconds>(end - start).count();
std::cout << "Synchronization completed in " << duration_ms << " ms." << std::endl;
verifyConsistency();
}
void verifyConsistency() {
std::cout << "Verifying consistency between nodes..." << std::endl;
auto &data1 = node1.get_data();
auto &data2 = node2.get_data();
bool consistent = (data1.size() == data2.size());
if (consistent) {
for (const auto &[rid, record] : data1) {
auto it = data2.find(rid);
if (it == data2.end() || !(it->second == record)) {
consistent = false;
break;
}
}
}
if (consistent) {
std::cout << "Consistency check passed: Both nodes have identical data." << std::endl;
} else {
std::cout << "Consistency check failed: Nodes have differing data." << std::endl;
}
}
};
int main() {
CrdtNodeId node1_id = 1;
CrdtNodeId node2_id = 2;
CrdtBenchmark benchmark(node1_id, node2_id);
benchmark.runBenchmark();
return 0;
}