/ benches / parser_bench.rs
parser_bench.rs
  1  use criterion::{black_box, criterion_group, criterion_main, Criterion};
  2  use korni::Korni;
  3  
  4  fn benchmark_parser(c: &mut Criterion) {
  5      let simple_env = "KEY=value\nANOTHER_KEY=another_value\n# Comment\nEXPORTED=true";
  6      
  7      let mut group = c.benchmark_group("parser");
  8      
  9      group.bench_function("simple_env", |b| {
 10          b.iter(|| {
 11              let _ = Korni::from_str(black_box(simple_env)).parse();
 12          })
 13      });
 14      
 15      // Create a larger synthetic payload
 16      let mut large_env = String::new();
 17      for i in 0..1000 {
 18          large_env.push_str(&format!("KEY_{}=value_{}\n", i, i));
 19          large_env.push_str(&format!("# Comment {}\n", i));
 20          large_env.push_str(&format!("QUOTED_{}=\"some quoted value with number {}\"\n", i, i));
 21      }
 22      
 23      group.bench_function("large_env_1k_lines", |b| {
 24          b.iter(|| {
 25              let _ = Korni::from_str(black_box(&large_env)).parse();
 26          })
 27      });
 28      
 29      // Benchmark just the iterator (parsing without HashMap construction)
 30      group.bench_function("iterator_only_large", |b| {
 31          b.iter(|| {
 32              let builder = Korni::from_str(black_box(&large_env));
 33              // We need to bypass .parse() which constructs Environment
 34              // So we use parsing logic directly or a helper if available,
 35              // but .parse() is the public API.
 36              // Let's benchmark the high-level API as that's what users use.
 37              let _ = builder.parse();
 38          })
 39      });
 40      
 41      group.finish();
 42  }
 43  
 44  fn benchmark_error_handling(c: &mut Criterion) {
 45      let mut error_env = String::new();
 46      for i in 0..1000 {
 47          // Mix of valid and invalid entries
 48          if i % 10 == 0 {
 49              // Invalid: space around equals
 50              error_env.push_str(&format!("KEY_{} = value_{}\n", i, i));
 51          } else if i % 7 == 0 {
 52              // Invalid: starts with digit
 53              error_env.push_str(&format!("{}KEY=value_{}\n", i, i));
 54          } else if i % 5 == 0 {
 55              // Invalid: double equals
 56              error_env.push_str(&format!("KEY_{}==value_{}\n", i, i));
 57          } else {
 58              // Valid
 59              error_env.push_str(&format!("KEY_{}=value_{}\n", i, i));
 60          }
 61      }
 62      
 63      let mut group = c.benchmark_group("error_handling");
 64      
 65      group.bench_function("error_heavy_1k_lines", |b| {
 66          b.iter(|| {
 67              let _ = Korni::from_str(black_box(&error_env)).parse();
 68          })
 69      });
 70      
 71      group.finish();
 72  }
 73  
 74  fn benchmark_quote_types(c: &mut Criterion) {
 75      let mut single_quoted = String::new();
 76      let mut double_quoted = String::new();
 77      let mut unquoted = String::new();
 78      
 79      for i in 0..1000 {
 80          single_quoted.push_str(&format!("KEY_{}='value_{}'\n", i, i));
 81          double_quoted.push_str(&format!("KEY_{}=\"value_{}\"\n", i, i));
 82          unquoted.push_str(&format!("KEY_{}=value_{}\n", i, i));
 83      }
 84      
 85      let mut group = c.benchmark_group("quote_types");
 86      
 87      group.bench_function("single_quoted_1k_lines", |b| {
 88          b.iter(|| {
 89              let _ = Korni::from_str(black_box(&single_quoted)).parse();
 90          })
 91      });
 92      
 93      group.bench_function("double_quoted_1k_lines", |b| {
 94          b.iter(|| {
 95              let _ = Korni::from_str(black_box(&double_quoted)).parse();
 96          })
 97      });
 98      
 99      group.bench_function("unquoted_1k_lines", |b| {
100          b.iter(|| {
101              let _ = Korni::from_str(black_box(&unquoted)).parse();
102          })
103      });
104      
105      group.finish();
106  }
107  
108  fn benchmark_comment_heavy(c: &mut Criterion) {
109      let mut comment_heavy = String::new();
110      
111      for i in 0..1000 {
112          comment_heavy.push_str(&format!("# This is comment number {}\n", i));
113          comment_heavy.push_str(&format!("# With multiple lines\n"));
114          comment_heavy.push_str(&format!("KEY_{}=value_{}\n", i, i));
115      }
116      
117      let mut group = c.benchmark_group("comments");
118      
119      group.bench_function("comment_heavy_1k_lines", |b| {
120          b.iter(|| {
121              let _ = Korni::from_str(black_box(&comment_heavy)).parse();
122          })
123      });
124      
125      group.bench_function("comment_heavy_with_tracking", |b| {
126          b.iter(|| {
127              let _ = Korni::from_str(black_box(&comment_heavy))
128                  .preserve_comments()
129                  .track_positions()
130                  .parse();
131          })
132      });
133      
134      group.finish();
135  }
136  
137  criterion_group!(benches, benchmark_parser, benchmark_error_handling, benchmark_quote_types, benchmark_comment_heavy);
138  criterion_main!(benches);