This document provides performance benchmarks, optimization tips, and best practices for using the Fairness Pipeline Development Toolkit efficiently.
The toolkit includes a comprehensive benchmark suite located in the benchmarks/ directory:
benchmark_metrics_100k.py: Benchmarks fairness metrics computation on 100k samplesbenchmark_pipeline.py: Benchmarks pipeline operations across different dataset sizesbenchmark_bootstrap.py: Benchmarks bootstrap confidence interval computationA pytest-based performance test suite is available in tests/performance/test_performance_suite.py:
Running Performance Tests:
# Run all performance tests
pytest tests/performance/test_performance_suite.py -v
# Run with performance markers
pytest -m performance -v
A profiling script is available to identify bottlenecks in critical paths:
scripts/profile_performance.py: Uses cProfile to profile critical operationsRunning Profiling:
# Run profiling script
python scripts/profile_performance.py
# Save profile data for detailed analysis
python -m cProfile -o profile.stats scripts/profile_performance.py
python -m pstats profile.stats
# Run all benchmarks
python benchmarks/benchmark_metrics_100k.py
python benchmarks/benchmark_pipeline.py
python benchmarks/benchmark_bootstrap.py
Metrics Computation (100k samples):
Pipeline Operations:
Bootstrap Confidence Intervals:
Note: Actual performance depends on hardware, dataset characteristics, and Python version.
Fairness Metrics:
Pipeline Operations:
Intersectional Analysis:
ci_method="percentile" for faster computationci_samples for quicker results (at cost of accuracy)with_ci=False# Fast check without CI
result = analyzer.demographic_parity_difference(
y_pred=y_pred,
sensitive=sensitive,
with_ci=False # Skip bootstrap CI computation
)
# Faster CI method
result = analyzer.demographic_parity_difference(
y_pred=y_pred,
sensitive=sensitive,
with_ci=True,
ci_method="percentile", # Faster than "bca"
ci_samples=500 # Fewer samples = faster
)
# Lower threshold for faster computation (use with caution)
analyzer = FairnessAnalyzer(min_group_size=20) # Default is 30
# Process in batches
batch_size = 10_000
for i in range(0, len(df), batch_size):
batch = df.iloc[i:i + batch_size]
result = analyzer.demographic_parity_difference(
y_pred=batch["y_pred"].to_numpy(),
sensitive=batch["gender"].to_numpy(),
with_ci=False # Disable CI for batch processing
)
# Cache metric results if computing multiple times
from functools import lru_cache
@lru_cache(maxsize=128)
def compute_metric_cached(y_pred_hash, sensitive_hash):
# Compute metric
return analyzer.demographic_parity_difference(...)
# Native backend is typically fastest
analyzer = FairnessAnalyzer(backend="native")
For very large datasets, consider parallel processing:
from multiprocessing import Pool
def compute_metric_for_group(args):
group_name, group_data = args
return analyzer.demographic_parity_difference(
y_pred=group_data["y_pred"],
sensitive=group_data["sensitive"]
)
# Process groups in parallel
with Pool() as pool:
results = pool.map(compute_metric_for_group, group_data_list)
| Dataset Size | Recommended Approach | Notes |
|---|---|---|
| < 10k samples | Full analysis with CI | Fast enough for interactive use |
| 10k - 100k samples | Full analysis, consider reducing CI samples | Good balance of speed and accuracy |
| 100k - 1M samples | Batch processing or sampling | Use with_ci=False for quick checks |
| > 1M samples | Sampling or distributed processing | Consider using Spark/Dask for very large datasets |
min_group_size values reduce computation time but may exclude important groupsTypical Memory Footprint:
Memory Optimization:
with_ci=False to reduce memory usageint8 instead of int64 when possible)# Profile memory usage
import tracemalloc
tracemalloc.start()
result = analyzer.demographic_parity_difference(
y_pred=y_pred,
sensitive=sensitive,
with_ci=True
)
current, peak = tracemalloc.get_traced_memory()
print(f"Peak memory: {peak / 1024 / 1024:.2f} MB")
tracemalloc.stop()
def process_in_chunks(df, chunk_size=10000):
for i in range(0, len(df), chunk_size):
yield df.iloc[i:i + chunk_size]
result = analyzer.demographic_parity_difference(...)
# Process result
del result # Explicitly free memory if needed
from scipy.sparse import csr_matrix
# Use sparse matrices for very sparse data
The toolkit includes performance benchmarks and test suite that can be integrated into CI/CD pipelines:
Using Performance Test Suite:
# .github/workflows/ci.yml
- name: Run performance tests
run: |
pytest tests/performance/test_performance_suite.py -v
# Tests will fail if performance degrades beyond baselines
Using Benchmark Scripts:
# .github/workflows/ci.yml
- name: Run performance benchmarks
run: |
python benchmarks/benchmark_metrics_100k.py > benchmark_metrics.txt
python benchmarks/benchmark_pipeline.py > benchmark_pipeline.txt
# Check for performance regressions
python -c "
import re
with open('benchmark_metrics.txt') as f:
content = f.read()
# Extract timing information and check thresholds
# Fail if performance degrades significantly
"
Track performance over time:
# Log performance metrics
import time
import json
start = time.time()
result = analyzer.demographic_parity_difference(...)
duration = time.time() - start
performance_log = {
"metric": "demographic_parity_difference",
"duration": duration,
"n_samples": len(y_pred),
"timestamp": time.time()
}
# Save to file or send to monitoring system
with open("performance_log.json", "a") as f:
f.write(json.dumps(performance_log) + "\n")
Establish performance baselines for your use case:
# Run benchmarks and save results
python benchmarks/benchmark_metrics_100k.py > baseline_metrics.txt
python benchmarks/benchmark_pipeline.py > baseline_pipeline.txt
# Compare against baselines in CI
python -c "
# Load baseline and current results
# Compare and fail if performance degrades > 20%
"
with_ci=False for initial explorationSymptoms: Metrics take > 10 seconds for 100k samples
Solutions:
ci_samples if CI is neededSymptoms: Memory usage > 500 MB for 100k samples
Solutions:
Symptoms: Pipeline operations take > 5 seconds for 10k samples
Solutions:
benchmarks/README.md for detailed benchmark documentationdocs/api.md for complete API documentationdocs/integration_guide.md for integration examples| Backend | Speed | Features | Dependencies |
|---|---|---|---|
| Native | Fastest | Core metrics | None (always available) |
| Fairlearn | Medium | Additional metrics | fairlearn |
| Aequitas | Slower | Comprehensive reports | aequitas |
Recommendation: Use native backend unless you need specific adapter features.
| Method | Speed | Accuracy | Use Case |
|---|---|---|---|
| Percentile | Fast | Good | General use |
| BCa | Slower | Better | When accuracy is critical |
Recommendation: Use percentile for most cases, BCa when accuracy is critical.
For questions or performance issues, see the Integration Guide or open an issue on GitHub.