int main() { m_clock.OnInitialize(); cauchy_256_init(); m_clock.usec(); cout << "Cauchy RS Codec Unit Tester" << endl; order_test(); int block_bytes = 8 * 162; // a multiple of 8 cout << "Using " << block_bytes << " bytes per block (ie. packet/chunk size); must be a multiple of 8 bytes" << endl; Abyssinian prng; prng.Initialize(m_clock.msec(), Clock::cycles()); u8 heat_map[256 * 256] = { 0 }; for (int block_count = 1; block_count < 256; ++block_count) { #ifdef CAT_REASONABLE_RECOVERY_COUNT for (int recovery_block_count = 1; recovery_block_count <= (block_count / 2) && recovery_block_count < (256 - block_count); ++recovery_block_count) { #else for (int recovery_block_count = 1; recovery_block_count < (256 - block_count); ++recovery_block_count) { #endif u8 *data = new u8[block_bytes * block_count]; u8 *recovery_blocks = new u8[block_bytes * recovery_block_count]; Block *blocks = new Block[block_count]; const u8 *data_ptrs[256]; for (int ii = 0; ii < block_count; ++ii) { data_ptrs[ii] = data + ii * block_bytes; } double sum_encode = 0; int erasures_count; #ifdef CAT_WORST_CASE_BENCHMARK erasures_count = recovery_block_count; if (block_count < erasures_count) { erasures_count = block_count; } { #else # ifdef CAT_ENCODE_TIMES_ONLY for (erasures_count = 1; erasures_count <= 4 && erasures_count <= recovery_block_count && erasures_count <= block_count; ++erasures_count) { # else for (erasures_count = 1; erasures_count <= recovery_block_count && erasures_count <= block_count; ++erasures_count) { # endif #endif for (int ii = 0; ii < block_bytes * block_count; ++ii) { data[ii] = (u8)prng.Next(); } double t0 = m_clock.usec(); assert(!cauchy_256_encode(block_count, recovery_block_count, data_ptrs, recovery_blocks, block_bytes)); double t1 = m_clock.usec(); double encode_time = t1 - t0; sum_encode += encode_time; cout << "Encoded k=" << block_count << " data blocks with m=" << recovery_block_count << " recovery blocks in " << encode_time << " usec : " << (block_bytes * block_count / encode_time) << " MB/s" << endl; #ifndef CAT_ENCODE_TIMES_ONLY for (int ii = 0; ii < erasures_count; ++ii) { int erasure_index = recovery_block_count - ii - 1; blocks[ii].data = recovery_blocks + erasure_index * block_bytes; blocks[ii].row = block_count + erasure_index; } for (int ii = erasures_count; ii < block_count; ++ii) { blocks[ii].data = data + ii * block_bytes; blocks[ii].row = ii; } t0 = m_clock.usec(); assert(!cauchy_256_decode(block_count, recovery_block_count, blocks, block_bytes)); t1 = m_clock.usec(); double decode_time = t1 - t0; cout << "+ Decoded " << erasures_count << " erasures in " << decode_time << " usec : " << (block_bytes * block_count / decode_time) << " MB/s" << endl; /* for (int ii = 0; ii < erasures_count; ++ii) { const u8 *orig = data + ii * block_bytes; print(orig, block_bytes / 8); print(blocks[ii].data, block_bytes / 8); } */ for (int ii = 0; ii < erasures_count; ++ii) { const u8 *orig = data + ii * block_bytes; assert(!memcmp(blocks[ii].data, orig, block_bytes)); } #endif // CAT_ENCODE_TIMES_ONLY } double avg_encode = sum_encode / erasures_count; int speed = block_bytes * block_count / avg_encode; u8 map_value = 0; if (speed < 10) { map_value = 1; } else if (speed < 50) { map_value = 2; } else if (speed < 100) { map_value = 3; } else if (speed < 200) { map_value = 4; } else if (speed < 300) { map_value = 5; } else if (speed < 400) { map_value = 6; } else if (speed < 500) { map_value = 7; } else { map_value = 8; } heat_map[block_count * 256 + recovery_block_count] = map_value; delete []data; delete []recovery_blocks; delete []blocks; } } ofstream file; file.open("docs/heatmap.txt"); for (int ii = 0; ii < 256; ++ii) { for (int jj = 0; jj < 256; ++jj) { u8 map_value = heat_map[ii * 256 + jj]; file << (int)map_value << " "; } file << endl; } m_clock.OnFinalize(); return 0; }
int main() { m_clock.OnInitialize(); //FindBadDenseSeeds(); for (int ii = 64; ii <= 64000; ii += 1000) { int block_count = ii; int block_bytes = 1500; int message_bytes = block_bytes * block_count; u8 *message = new u8[message_bytes]; u8 *message_out = new u8[message_bytes]; u8 *block = new u8[block_bytes]; for (int ii = 0; ii < message_bytes; ++ii) { message[ii] = ii; } wirehair::Encoder encoder; double start = m_clock.usec(); wirehair::Result r = encoder.BeginEncode(message, message_bytes, block_bytes); double end = m_clock.usec(); if (r) { cout << "-- FAIL! N=" << encoder.BlockCount() << " encoder.BeginEncode error " << wirehair::GetResultString(r) << endl; cin.get(); continue; } else { double mbytes = message_bytes / 1000000.; cout << ">> OKAY! N=" << encoder.BlockCount() << "(" << mbytes << " MB) encoder.BeginEncode in " << end - start << " usec, " << message_bytes / (end - start) << " MB/s" << endl; //cin.get(); } Abyssinian prng; cat::wirehair::Decoder decoder; u32 overhead_sum = 0, overhead_trials = 0; u32 drop_seed = 50002; double time_sum = 0; const int trials = 1000; for (int jj = 0; jj < trials; ++jj) { int blocks_needed = 0; wirehair::Result s = decoder.BeginDecode(message_out, message_bytes, block_bytes); if (s) { cout << "-- FAIL! N=" << decoder.BlockCount() << " decoder.BeginDecode error " << wirehair::GetResultString(s) << endl; cin.get(); return 1; } prng.Initialize(drop_seed); for (u32 id = 0;; ++id) { if (prng.Next() & 1) continue; encoder.Encode(id, block); ++blocks_needed; double start = m_clock.usec(); wirehair::Result r = decoder.Decode(id, block); double end = m_clock.usec(); if (r != wirehair::R_MORE_BLOCKS) { if (r == wirehair::R_WIN) { u32 overhead = blocks_needed - decoder.BlockCount(); overhead_sum += overhead; ++overhead_trials; //cout << ">> OKAY! N=" << decoder.BlockCount() << " decoder.Decode in " << end - start << " usec, " << message_bytes / (end - start) << " MB/s after " << overhead << " extra blocks. Average extra = " << overhead_sum / (double)overhead_trials << ". Seed = " << drop_seed << endl; time_sum += end - start; if (!memcmp(message, message_out, message_bytes)) { //cout << "Match!" << endl; } else { cout << "FAAAAAIL! Seed = " << drop_seed << endl; for (int ii = 0; ii < message_bytes; ++ii) { if (message_out[ii] != message[ii]) cout << ii << " : " << (int)message_out[ii] << endl; } cin.get(); } } else { cout << "-- FAIL! N=" << decoder.BlockCount() << " decoder.Decode error " << wirehair::GetResultString(r) << " from drop seed " << drop_seed << endl; overhead_sum += 1; ++overhead_trials; //cin.get(); } //cin.get(); break; } } ++drop_seed; } double avg_time = time_sum / trials; double avg_overhead = overhead_sum / (double)overhead_trials; double avg_bytes = message_bytes * (decoder.BlockCount() + avg_overhead) / (double)decoder.BlockCount() - message_bytes; cout << "N=" << decoder.BlockCount() << " decoder.Decode in " << avg_time << " usec, " << message_bytes / avg_time << " MB/s. Average overhead = " << avg_overhead << " (" << avg_bytes << " bytes)" << endl; } m_clock.OnFinalize(); return 0; }