benchkit 0.21.0

Lightweight benchmarking toolkit focused on practical performance analysis and report generation. Non-restrictive alternative to criterion, designed for easy integration and markdown report generation.
Documentation
//! Testing benchkit with actual `strs_tools` algorithms
//!
//! This tests benchkit integration with the actual specialized algorithms
//! from `strs_tools` to ensure real-world compatibility.

#![allow(clippy ::format_push_string)]
#![allow(clippy ::uninlined_format_args)]
#![allow(clippy ::std_instead_of_core)]
#![allow(clippy ::unnecessary_wraps)]
#![allow(clippy ::useless_format)]
#![allow(clippy ::redundant_closure_for_method_calls)]
#![allow(clippy ::cast_possible_truncation)]
#![allow(clippy ::cast_sign_loss)]
#![allow(clippy ::needless_borrows_for_generic_args)]
#![allow(clippy ::doc_markdown)]

use benchkit ::prelude :: *;

type Result< T > = core ::result ::Result< T, Box<dyn core ::error ::Error >>;

// Import strs_tools (conditional compilation for when available)
// #[ cfg(feature = "integration") ]
// use strs_tools ::string ::specialized :: {
//     smart_split, SingleCharSplitIterator, BoyerMooreSplitIterator
// };

fn main() -> Result< () >
{
  println!("๐Ÿ”ง Testing Benchkit with Actual strs_tools Integration");
  println!("=======================================================");
  println!();

  // Test 1 : Basic string operations (always available)
  test_standard_string_operations();
  
  // Test 2 : strs_tools specialized algorithms (simulation)
  test_strs_tools_specialized_algorithms();
  
  // Test 3 : Performance profiling of real algorithms
  test_real_world_performance_profiling();
  
  // Test 4 : Edge case handling
  test_edge_case_handling();
  
  // Test 5 : Large data set handling
  test_large_dataset_performance();

  println!("โœ… All strs_tools integration tests completed!");
  
  Ok(())
}

fn test_standard_string_operations()
{
  println!("1๏ธโƒฃ Testing Standard String Operations");
  println!("------------------------------------");
  
  // Generate realistic test data
  let single_char_data = DataGenerator ::new()
  .pattern("field{},value{},")
  .repetitions(1000)
  .complexity(DataComplexity ::Medium)
  .generate_string();
  
  let multi_char_data = DataGenerator ::new()
  .pattern("ns{} ::class{} :: ")
  .repetitions(500)
  .complexity(DataComplexity ::Medium)  
  .generate_string();

  println!("  ๐Ÿ“Š Test data: ");
  println!("     - Single char: {} bytes, {} commas", 
   single_char_data.len(), 
   single_char_data.matches(',').count());
  println!("     - Multi char: {} bytes, {} double colons", 
   multi_char_data.len(),
   multi_char_data.matches(" :: ").count());

  // Test single character splitting performance
  let single_data_clone = single_char_data.clone();
  let single_data_clone2 = single_char_data.clone();
  let single_data_clone3 = single_char_data.clone();
  
  let mut single_char_comparison = ComparativeAnalysis ::new("single_char_splitting_comparison");
  
  single_char_comparison = single_char_comparison
  .algorithm("std_split", move || {
   let count = single_data_clone.split(',').count();
   core ::hint ::black_box(count);
 })
  .algorithm("std_matches", move || {
   let count = single_data_clone2.matches(',').count();
   core ::hint ::black_box(count);
 })
  .algorithm("manual_byte_scan", move || {
   let count = single_data_clone3.bytes().filter(|&b| b == b',').count();
   core ::hint ::black_box(count);
 });

  let single_report = single_char_comparison.run();
  
  if let Some((fastest_single, result)) = single_report.fastest() 
  {
  println!("  โœ… Single char analysis: ");
  let ops_per_sec = result.operations_per_second();
  println!("     - Fastest: {fastest_single} ({ops_per_sec:.0} ops/sec)");
  println!("     - Reliability: CV = {:.1}%", result.coefficient_of_variation() * 100.0);
 }

  // Test multi character splitting
  let multi_data_clone = multi_char_data.clone();
  let multi_data_clone2 = multi_char_data.clone();
  
  let mut multi_char_comparison = ComparativeAnalysis ::new("multi_char_splitting_comparison");
  
  multi_char_comparison = multi_char_comparison
  .algorithm("std_split", move || {
   let count = multi_data_clone.split(" :: ").count();
   core ::hint ::black_box(count);
 })
  .algorithm("std_matches", move || {
   let count = multi_data_clone2.matches(" :: ").count();
   core ::hint ::black_box(count);
 });

  let multi_report = multi_char_comparison.run();
  
  if let Some((fastest_multi, result)) = multi_report.fastest() 
  {
  println!("  โœ… Multi char analysis: ");
  let ops_per_sec = result.operations_per_second();
  println!("     - Fastest: {fastest_multi} ({ops_per_sec:.0} ops/sec)");
  println!("     - Reliability: CV = {:.1}%", result.coefficient_of_variation() * 100.0);
 }

  println!();
}

fn test_strs_tools_specialized_algorithms()
{
  println!("2๏ธโƒฃ Testing strs_tools Specialized Algorithms (Simulation)");
  println!("----------------------------------------------------------");
  
  let test_data = DataGenerator ::new()
  .pattern("item{},field{},")
  .repetitions(2000)
  .complexity(DataComplexity ::Complex)
  .generate_string();
  
  let test_data_len = test_data.len();
  println!("  ๐Ÿ“Š Test data: {test_data_len} bytes");

  let test_data_clone = test_data.clone();
  let test_data_clone2 = test_data.clone();
  let test_data_clone3 = test_data.clone();
  
  let mut specialized_comparison = ComparativeAnalysis ::new("specialized_algorithms_comparison");
  
  specialized_comparison = specialized_comparison
  .algorithm("generic_split", move || {
   // Simulating generic split algorithm
   let count = test_data_clone.split(',').count();
   core ::hint ::black_box(count);
 })
  .algorithm("single_char_specialized_sim", move || {
   // Simulating single char specialized split
   let count = test_data_clone2.split(',').count();
   core ::hint ::black_box(count);
 })
  .algorithm("smart_split_auto_sim", move || {
   // Simulating smart split algorithm
   let count = test_data_clone3.split(',').count();
   std ::thread ::sleep(core ::time ::Duration ::from_nanos(500)); // Simulate slightly slower processing
   core ::hint ::black_box(count);
 });

  let specialized_report = specialized_comparison.run();
  
  if let Some((fastest, result)) = specialized_report.fastest() 
  {
  println!("  โœ… Specialized algorithms analysis: ");
  println!("     - Fastest: {} ({:.0} ops/sec)", fastest, result.operations_per_second());
  println!("     - Reliability: CV = {:.1}%", result.coefficient_of_variation() * 100.0);
 }

  // Test Boyer-Moore for multi-character patterns
  let multi_test_data = DataGenerator ::new()
  .pattern("ns{} ::class{} :: ")
  .repetitions(1000)
  .complexity(DataComplexity ::Complex)
  .generate_string();

  let multi_data_clone = multi_test_data.clone();
  let multi_data_clone2 = multi_test_data.clone();

  let mut boyer_moore_comparison = ComparativeAnalysis ::new("boyer_moore_comparison");
  
  boyer_moore_comparison = boyer_moore_comparison
  .algorithm("generic_multi_split", move || {
   let count = multi_data_clone.split(" :: ").count();
   core ::hint ::black_box(count);
 })
  .algorithm("boyer_moore_specialized_sim", move || {
   // Simulating Boyer-Moore pattern matching  
   let count = multi_data_clone2.split(" :: ").count();
   std ::thread ::sleep(core ::time ::Duration ::from_nanos(200)); // Simulate slightly different performance
   core ::hint ::black_box(count);
 });

  let boyer_report = boyer_moore_comparison.run();
  
  if let Some((fastest_boyer, result)) = boyer_report.fastest() 
  {
  println!("  โœ… Boyer-Moore analysis: ");
  println!("     - Fastest: {} ({:.0} ops/sec)", fastest_boyer, result.operations_per_second());
  println!("     - Reliability: CV = {:.1}%", result.coefficient_of_variation() * 100.0);
 }

  println!();
}

fn test_real_world_performance_profiling()
{
  println!("3๏ธโƒฃ Testing Real-World Performance Profiling");
  println!("-------------------------------------------");
  
  // Simulate realistic parsing scenarios from unilang
  let unilang_commands = DataGenerator ::new()
  .complexity(DataComplexity ::Full)
  .generate_unilang_commands(100);
  
  let command_text = unilang_commands.join(" ");
  
  println!("  ๐Ÿ“Š Unilang data: {} commands, {} total chars", 
   unilang_commands.len(), 
   command_text.len());

  // Test memory usage of different parsing approaches  
  let memory_benchmark = MemoryBenchmark ::new("unilang_command_parsing");
  
  let cmd_clone = command_text.clone();
  let cmd_clone2 = command_text.clone();
  
  let memory_comparison = memory_benchmark.compare_memory_usage(
  "split_and_collect_all",
  move || {
   let parts: Vec< &str > = cmd_clone.split_whitespace().collect();
   core ::hint ::black_box(parts.len());
 },
  "iterator_count_only", 
  move || {
   let count = cmd_clone2.split_whitespace().count();
   core ::hint ::black_box(count);
 },
  15,
 );
  
  let (efficient_name, efficient_stats) = memory_comparison.more_memory_efficient();
  let reduction = memory_comparison.memory_reduction_percentage();
  
  println!("  โœ… Memory efficiency analysis: ");
  println!("     - More efficient: {} ({:.1}% reduction)", efficient_name, reduction);
  println!("     - Peak memory: {} bytes", efficient_stats.peak_usage);
  println!("     - Total allocations: {}", efficient_stats.allocation_count);

  // Test throughput analysis 
  let throughput_analyzer = ThroughputAnalyzer ::new("command_processing", command_text.len() as u64)
  .with_items(unilang_commands.len() as u64);
  
  let mut throughput_results = std ::collections ::HashMap ::new();
  
  // Simulate different processing speeds
  let fast_times = vec![core ::time ::Duration ::from_micros(100); 20];
  throughput_results.insert("optimized_parser".to_string(), 
   BenchmarkResult ::new("optimized", fast_times));
  
  let slow_times = vec![core ::time ::Duration ::from_micros(500); 20];
  throughput_results.insert("generic_parser".to_string(), 
   BenchmarkResult ::new("generic", slow_times));
  
  let throughput_comparison = throughput_analyzer.compare_throughput(&throughput_results);
  
  if let Some((fastest_name, fastest_metrics)) = throughput_comparison.fastest_throughput() 
  {
  println!("  โœ… Throughput analysis: ");
  println!("     - Fastest: {} ({})", fastest_name, fastest_metrics.throughput_description());
  if let Some(items_desc) = fastest_metrics.items_description() 
  {
   println!("     - Command processing: {}", items_desc);
 }
 }
  
  println!();
}

fn test_edge_case_handling()
{
  println!("4๏ธโƒฃ Testing Edge Case Handling");
  println!("-----------------------------");
  
  // Test empty strings, single characters, repeated delimiters
  let edge_cases = vec![
  ("empty_string", String ::new()),
  ("single_char", "a".to_string()),
  ("only_delimiters", ",,,,,".to_string()),
  ("no_delimiters", "abcdefghijk".to_string()),
  ("mixed_unicode", "hello,๐Ÿฆ€,world,ๆต‹่ฏ•,end".to_string()),
 ];
  
  println!("  ๐Ÿงช Testing {} edge cases", edge_cases.len());
  
  let mut suite = BenchmarkSuite ::new("edge_case_handling");
  
  for (name, test_data) in edge_cases 
  {
  let data_clone = test_data.clone();
  let benchmark_name = format!("split_{name}");
  
  suite.benchmark(benchmark_name, move || {
   let count = data_clone.split(',').count();
   core ::hint ::black_box(count);
 });
 }
  
  let results = suite.run_analysis();
  
  println!("  โœ… Edge case analysis completed");
  println!("     - {} test cases processed", results.results.len());
  
  let mut reliable_count = 0;
  let mut total_count = 0;
  
  for (name, result) in &results.results 
  {
  total_count += 1;
  let is_reliable = result.is_reliable();
  if is_reliable { reliable_count += 1; }
  
  let cv = result.coefficient_of_variation() * 100.0;
  let status = if is_reliable { "โœ…" } else { "โš ๏ธ" };
  
  println!("     - {name} : {status} (CV: {cv:.1}%)");
 }
  
  println!("     - Reliability: {}/{} cases meet standards", reliable_count, total_count);
  
  println!();
}

fn test_large_dataset_performance()
{
  println!("5๏ธโƒฃ Testing Large Dataset Performance");
  println!("-----------------------------------");
  
  // Generate large datasets to test scaling characteristics
  let scales = vec![1000, 10000, 100_000];
  
  for &scale in &scales 
  {
  println!("  ๐Ÿ“Š Testing scale: {} items", scale);
  
  let large_data = DataGenerator ::new()
   .pattern("record{},field{},value{},")
   .repetitions(scale)
   .complexity(DataComplexity ::Medium)
   .generate_string();
  
  println!("     Data size: {:.1} MB", large_data.len() as f64 / 1_048_576.0);
  
  // Test single measurement to check for performance issues
  let data_clone = large_data.clone();
  let start = std ::time ::Instant ::now();
  let count = data_clone.split(',').count();
  let duration = start.elapsed();
  
  let throughput = large_data.len() as f64 / duration.as_secs_f64();
  let items_per_sec = count as f64 / duration.as_secs_f64();
  
  println!("     Processing time: {:.2?}", duration);
  println!("     Throughput: {:.1} MB/s", throughput / 1_048_576.0);
  println!("     Items/sec: {:.0}", items_per_sec);
  
  // Check for memory issues with large datasets
  let memory_test = MemoryBenchmark ::new(&format!("large_dataset_{}", scale));
  let data_clone2 = large_data.clone();
  
  let (_result, stats) = memory_test.run_with_tracking(1, move || {
   let count = data_clone2.split(',').count();
   core ::hint ::black_box(count);
 });
  
  println!("     Memory overhead: {} bytes", stats.total_allocated);
  println!();
 }
  
  println!("  โœ… Large dataset testing completed - no performance issues detected");
  println!();
}