debtmap 0.23.0

Code complexity and technical debt analyzer
Documentation
//! Benchmark for pure tier classification functions (Spec 224)
//!
//! Validates that tier classification has acceptable performance
//! and ensures no regression after refactoring to smaller functions.

use criterion::{BenchmarkId, Criterion, criterion_group, criterion_main};
use debtmap::priority::tiers::pure::classify_tier;
use debtmap::priority::{
    ActionableRecommendation, DebtType, FunctionRole, ImpactMetrics, Location, TierConfig,
    UnifiedDebtItem, UnifiedScore,
};
use std::hint::black_box;
use std::path::PathBuf;

fn create_test_item(
    debt_type: DebtType,
    cyclomatic: u32,
    cognitive: u32,
    nesting: u32,
    deps: usize,
    final_score: f64,
    complexity_factor: f64,
) -> UnifiedDebtItem {
    UnifiedDebtItem {
        location: Location {
            file: PathBuf::from("test.rs"),
            function: "test_fn".to_string(),
            line: 1,
        },
        debt_type,
        unified_score: UnifiedScore {
            complexity_factor,
            coverage_factor: 0.0,
            dependency_factor: 0.0,
            role_multiplier: 1.0,
            final_score: final_score.max(0.0),
            base_score: None,
            exponential_factor: None,
            risk_boost: None,
            pre_adjustment_score: None,
            adjustment_applied: None,
            purity_factor: None,
            refactorability_factor: None,
            pattern_factor: None,
            // Spec 260: Score transparency fields
            debt_adjustment: None,
            pre_normalization_score: None,
            structural_multiplier: Some(1.0),
            has_coverage_data: false,
            contextual_risk_multiplier: None,
            pre_contextual_score: None,
            debt_type_multiplier: None,
        },
        function_role: FunctionRole::PureLogic,
        recommendation: ActionableRecommendation {
            primary_action: "Test".into(),
            rationale: "Test".into(),
            implementation_steps: vec![],
            related_items: vec![],
            steps: None,
            estimated_effort_hours: None,
        },
        expected_impact: ImpactMetrics {
            risk_reduction: 0.0,
            complexity_reduction: 0.0,
            coverage_improvement: 0.0,
            lines_reduction: 0,
        },
        transitive_coverage: None,
        file_context: None,
        upstream_dependencies: deps,
        downstream_dependencies: deps,
        upstream_callers: vec![],
        downstream_callees: vec![],
        nesting_depth: nesting,
        function_length: 10,
        cyclomatic_complexity: cyclomatic,
        cognitive_complexity: cognitive,
        entropy_analysis: None,
        is_pure: Some(false),
        purity_confidence: Some(0.0),
        purity_level: None,
        error_swallowing_count: None,
        error_swallowing_patterns: None,
        god_object_indicators: None,
        tier: None,
        function_context: None,
        context_confidence: None,
        contextual_recommendation: None,
        pattern_analysis: None,
        context_multiplier: None,
        context_type: None,
        language_specific: None,
        detected_pattern: None,
        contextual_risk: None,
        file_line_count: None,
        responsibility_category: None,
        context_suggestion: None,
        // Spec 267: Production/test caller separation
        upstream_production_callers: vec![],
        upstream_test_callers: vec![],
        production_blast_radius: 0,
    }
}

fn bench_classify_god_object(c: &mut Criterion) {
    let config = TierConfig::default();
    let item = create_test_item(
        DebtType::GodObject {
            methods: 100,
            fields: Some(50),
            responsibilities: 5,
            god_object_score: 95.0,
            lines: 500,
        },
        10,
        10,
        2,
        5,
        5.0,
        2.0,
    );

    c.bench_function("classify_god_object", |b| {
        b.iter(|| classify_tier(black_box(&item), black_box(&config)))
    });
}

fn bench_classify_error_handling(c: &mut Criterion) {
    let config = TierConfig::default();
    let item = create_test_item(
        DebtType::ErrorSwallowing {
            pattern: "unwrap".into(),
            context: None,
        },
        10,
        10,
        2,
        5,
        5.0,
        2.0,
    );

    c.bench_function("classify_error_handling", |b| {
        b.iter(|| classify_tier(black_box(&item), black_box(&config)))
    });
}

fn bench_classify_complexity_hotspot(c: &mut Criterion) {
    let config = TierConfig::default();
    let item = create_test_item(
        DebtType::ComplexityHotspot {
            cyclomatic: 35,
            cognitive: 25,
        },
        35,
        25,
        3,
        5,
        6.0,
        3.0,
    );

    c.bench_function("classify_complexity_hotspot", |b| {
        b.iter(|| classify_tier(black_box(&item), black_box(&config)))
    });
}

fn bench_classify_testing_gap(c: &mut Criterion) {
    let config = TierConfig::default();
    let item = create_test_item(
        DebtType::TestingGap {
            coverage: 0.0,
            cyclomatic: 15,
            cognitive: 12,
        },
        15,
        12,
        2,
        5,
        3.0,
        1.5,
    );

    c.bench_function("classify_testing_gap", |b| {
        b.iter(|| classify_tier(black_box(&item), black_box(&config)))
    });
}

fn bench_classify_extreme_scores(c: &mut Criterion) {
    let config = TierConfig::default();

    let mut group = c.benchmark_group("classify_extreme_scores");

    // Extreme final score
    let item_extreme_score = create_test_item(
        DebtType::ComplexityHotspot {
            cyclomatic: 30,
            cognitive: 25,
        },
        30,
        25,
        3,
        5,
        11.0, // Extreme score
        3.0,
    );

    group.bench_function("extreme_final_score", |b| {
        b.iter(|| classify_tier(black_box(&item_extreme_score), black_box(&config)))
    });

    // Extreme cyclomatic
    let item_extreme_cyclomatic = create_test_item(
        DebtType::ComplexityHotspot {
            cyclomatic: 70,
            cognitive: 15,
        },
        70,
        15,
        2,
        5,
        5.0,
        2.0,
    );

    group.bench_function("extreme_cyclomatic", |b| {
        b.iter(|| classify_tier(black_box(&item_extreme_cyclomatic), black_box(&config)))
    });

    // Extreme cognitive
    let item_extreme_cognitive = create_test_item(
        DebtType::ComplexityHotspot {
            cyclomatic: 15,
            cognitive: 25,
        },
        15,
        25,
        2,
        5,
        5.0,
        2.0,
    );

    group.bench_function("extreme_cognitive", |b| {
        b.iter(|| classify_tier(black_box(&item_extreme_cognitive), black_box(&config)))
    });

    // Deep nesting
    let item_deep_nesting = create_test_item(
        DebtType::ComplexityHotspot {
            cyclomatic: 15,
            cognitive: 10,
        },
        15,
        10,
        5, // Deep nesting
        5,
        5.0,
        2.0,
    );

    group.bench_function("deep_nesting", |b| {
        b.iter(|| classify_tier(black_box(&item_deep_nesting), black_box(&config)))
    });

    group.finish();
}

fn bench_classify_batch(c: &mut Criterion) {
    let config = TierConfig::default();
    let mut group = c.benchmark_group("classify_batch");

    for size in [100, 500, 1000].iter() {
        let items: Vec<_> = (0..*size)
            .map(|i| {
                let debt_type = match i % 4 {
                    0 => DebtType::GodObject {
                        methods: 50 + (i % 50),
                        fields: Some(20 + (i % 30)),
                        responsibilities: 5,
                        god_object_score: 85.0,
                        lines: 300 + (i % 200),
                    },
                    1 => DebtType::ComplexityHotspot {
                        cyclomatic: 25 + (i % 40),
                        cognitive: 15 + (i % 20),
                    },
                    2 => DebtType::TestingGap {
                        coverage: 0.0,
                        cyclomatic: 10 + (i % 15),
                        cognitive: 10 + (i % 15),
                    },
                    _ => DebtType::ErrorSwallowing {
                        pattern: "unwrap".into(),
                        context: None,
                    },
                };

                create_test_item(
                    debt_type,
                    20 + (i % 30),
                    15 + (i % 20),
                    2 + (i % 3),
                    5 + (i % 10) as usize,
                    5.0 + (i as f64 % 5.0),
                    2.0 + (i as f64 % 3.0),
                )
            })
            .collect();

        group.bench_with_input(BenchmarkId::new("classify_items", size), size, |b, _| {
            b.iter(|| {
                for item in &items {
                    black_box(classify_tier(black_box(item), black_box(&config)));
                }
            })
        });
    }

    group.finish();
}

criterion_group!(
    benches,
    bench_classify_god_object,
    bench_classify_error_handling,
    bench_classify_complexity_hotspot,
    bench_classify_testing_gap,
    bench_classify_extreme_scores,
    bench_classify_batch
);
criterion_main!(benches);