This documentation is automatically generated by online-judge-tools/verification-helper
#!/usr/bin/env python3
"""
Simple boolean list benchmark using the new declarative framework.
Compares different boolean data structures and operations.
"""
import random
import array
import sys
import os
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
from cp_library.perf.benchmark import Benchmark, BenchmarkConfig
# Import optional dependencies
try:
import bitarray
HAS_BITARRAY = True
except ImportError:
HAS_BITARRAY = False
try:
from cp_library.ds.wavelet.bit_array_cls import BitArray
HAS_CUSTOM_BITARRAY = True
except ImportError:
HAS_CUSTOM_BITARRAY = False
# Configure benchmark
config = BenchmarkConfig(
name="bool_list",
sizes=[1000000, 100000, 10000, 1000, 100, 10, 1], # Reverse order to warm up JIT
operations=['construction', 'access', 'count', 'sum', 'flip', 'and', 'or'],
iterations=10,
warmup=2,
output_dir="./output/benchmark_results/bool_list"
)
# Create benchmark instance
benchmark = Benchmark(config)
# Data generator
@benchmark.data_generator("default")
def generate_bool_data(size: int, operation: str):
"""Generate boolean data in various formats"""
# Generate random boolean data
bool_list = [random.random() < 0.5 for _ in range(size)]
int_list = [int(b) for b in bool_list]
# Create different representations
array_b = array.array('b', int_list)
array_B = array.array('B', int_list)
# Pack into bytes (8 bits per byte)
bytes_data = bytearray((size + 7) // 8)
for i, bit in enumerate(bool_list):
if bit:
bytes_data[i // 8] |= 1 << (7 - (i % 8))
bytes_data = bytes(bytes_data)
# Create bitarray if available
bit_array = None
if HAS_BITARRAY:
bit_array = bitarray.bitarray(bool_list)
# Create custom BitArray if available
custom_bitarray = None
if HAS_CUSTOM_BITARRAY:
custom_bitarray = BitArray(int_list)
custom_bitarray.build()
# Pre-generate auxiliary data for binary operations
other_bool = [random.random() < 0.5 for _ in range(size)]
other_int = [int(b) for b in other_bool]
return {
'bool_list': bool_list,
'int_list': int_list,
'array_b': array_b,
'array_B': array_B,
'bytes_data': bytes_data,
'bit_array': bit_array,
'custom_bitarray': custom_bitarray,
'other_bool': other_bool,
'other_int': other_int,
'size': size,
'operation': operation
}
# Construction operations
@benchmark.implementation("list_bool", "construction")
def construction_list_bool(data):
"""Construct list[bool] from raw data"""
# Use the same source data for all implementations
raw_data = data['bool_list']
result = list(raw_data) # Create a copy
# Return consistent checksum based on source data
checksum = 0
for i, b in enumerate(raw_data):
if b:
checksum ^= i
return checksum
@benchmark.implementation("list_int", "construction")
def construction_list_int(data):
"""Construct list[int] from raw data"""
# Use the same source data for all implementations
raw_data = data['bool_list']
int_list = [int(b) for b in raw_data]
# Return consistent checksum based on source data
checksum = 0
for i, b in enumerate(raw_data):
if b:
checksum ^= i
return checksum
@benchmark.implementation("array_b", "construction")
def construction_array_b(data):
"""Construct array.array('b') from raw data"""
# Use the same source data for all implementations
raw_data = data['bool_list']
int_list = [int(b) for b in raw_data]
array_b = array.array('b', int_list)
# Return consistent checksum based on source data
checksum = 0
for i, b in enumerate(raw_data):
if b:
checksum ^= i
return checksum
@benchmark.implementation("array_B", "construction")
def construction_array_B(data):
"""Construct array.array('B') from raw data"""
# Use the same source data for all implementations
raw_data = data['bool_list']
int_list = [int(b) for b in raw_data]
array_B = array.array('B', int_list)
# Return consistent checksum based on source data
checksum = 0
for i, b in enumerate(raw_data):
if b:
checksum ^= i
return checksum
@benchmark.implementation("bytes", "construction")
def construction_bytes(data):
"""Construct bytes from raw data"""
# Use the same source data for all implementations
raw_data = data['bool_list']
size = data['size']
bytes_data = bytearray((size + 7) // 8)
for i, bit in enumerate(raw_data):
if bit:
bytes_data[i // 8] |= 1 << (7 - (i % 8))
bytes_data = bytes(bytes_data)
# Return consistent checksum based on source data
checksum = 0
for i, b in enumerate(raw_data):
if b:
checksum ^= i
return checksum
if HAS_BITARRAY:
@benchmark.implementation("bitarray", "construction")
def construction_bitarray(data):
"""Construct bitarray from raw data"""
# Use the same source data for all implementations
raw_data = data['bool_list']
bit_array = bitarray.bitarray(raw_data)
# Return consistent checksum based on source data
checksum = 0
for i, b in enumerate(raw_data):
if b:
checksum ^= i
return checksum
if HAS_CUSTOM_BITARRAY:
@benchmark.implementation("custom_bitarray", "construction")
def construction_custom_bitarray(data):
"""Construct custom BitArray from raw data"""
# Use the same source data for all implementations
raw_data = data['bool_list']
int_list = [int(b) for b in raw_data]
custom_bitarray = BitArray(int_list)
custom_bitarray.build()
# Return consistent checksum based on source data
checksum = 0
for i, b in enumerate(raw_data):
if b:
checksum ^= i
return checksum
# Access operations
@benchmark.implementation("list_bool", "access")
def access_list_bool(data):
"""Access operation on list[bool]"""
lst = data['bool_list']
total = 0
access_count = min(1000, len(lst))
step = max(1, len(lst) // access_count)
for i in range(0, len(lst), step):
if i < len(lst) and lst[i]:
total += 1
return total
@benchmark.implementation("list_int", "access")
def access_list_int(data):
"""Access operation on list[int]"""
lst = data['int_list']
total = 0
access_count = min(1000, len(lst))
step = max(1, len(lst) // access_count)
for i in range(0, len(lst), step):
if i < len(lst) and lst[i]:
total += 1
return total
@benchmark.implementation("array_b", "access")
def access_array_b(data):
"""Access operation on array.array('b')"""
arr = data['array_b']
total = 0
access_count = min(1000, len(arr))
step = max(1, len(arr) // access_count)
for i in range(0, len(arr), step):
if i < len(arr) and arr[i]:
total += 1
return total
# Count operations
@benchmark.implementation("list_bool", "count")
def count_list_bool(data):
"""Count True values in list[bool]"""
return data['bool_list'].count(True)
@benchmark.implementation("list_int", "count")
def count_list_int(data):
"""Count True values in list[int]"""
return sum(data['int_list'])
@benchmark.implementation("array_b", "count")
def count_array_b(data):
"""Count True values in array.array('b')"""
return sum(data['array_b'])
# Sum operations (same as count for boolean data)
@benchmark.implementation("list_bool", "sum")
def sum_list_bool(data):
"""Sum boolean values in list[bool]"""
return sum(data['bool_list'])
@benchmark.implementation("list_int", "sum")
def sum_list_int(data):
"""Sum boolean values in list[int]"""
return sum(data['int_list'])
@benchmark.implementation("array_b", "sum")
def sum_array_b(data):
"""Sum boolean values in array.array('b')"""
return sum(data['array_b'])
# Flip operations
@benchmark.implementation("list_bool", "flip")
def flip_list_bool(data):
"""Flip all boolean values in list[bool]"""
lst = list(data['bool_list']) # Create copy
checksum = 0
for i in range(len(lst)):
lst[i] = not lst[i]
if lst[i]:
checksum ^= i
return checksum
@benchmark.implementation("list_int", "flip")
def flip_list_int(data):
"""Flip all boolean values in list[int]"""
lst = list(data['int_list']) # Create copy
checksum = 0
for i in range(len(lst)):
lst[i] = 1 - lst[i]
if lst[i]:
checksum ^= i
return checksum
@benchmark.implementation("array_b", "flip")
def flip_array_b(data):
"""Flip all boolean values in array.array('b')"""
arr = array.array('b', data['array_b']) # Create copy
checksum = 0
for i in range(len(arr)):
arr[i] = 1 - arr[i]
if arr[i]:
checksum ^= i
return checksum
@benchmark.implementation("array_B", "flip")
def flip_array_B(data):
"""Flip all boolean values in array.array('B')"""
arr = array.array('B', data['array_B']) # Create copy
checksum = 0
for i in range(len(arr)):
arr[i] = 1 - arr[i]
if arr[i]:
checksum ^= i
return checksum
@benchmark.implementation("bytearray", "flip")
def flip_bytearray(data):
"""Flip all boolean values in bytearray (non-bit-packed)"""
# Use int_list as source for non-bit-packed
int_list = data['int_list']
result = bytearray(int_list) # Create copy
checksum = 0
for i in range(len(result)):
result[i] = 1 - result[i]
if result[i]:
checksum ^= i
return checksum
@benchmark.implementation("bytes", "flip")
def flip_bytes(data):
"""Flip all boolean values in bytes (non-bit-packed)"""
# Use int_list as source for non-bit-packed
int_list = data['int_list']
result = bytearray(int_list) # Convert to mutable
checksum = 0
for i in range(len(result)):
result[i] = 1 - result[i]
if result[i]:
checksum ^= i
result = bytes(result) # Convert back to immutable
return checksum
@benchmark.implementation("bytearray_packed", "flip")
def flip_bytearray_packed(data):
"""Flip all boolean values in bytearray (bit-packed)"""
# Use bit-packed bytes_data
size = data['size']
bytes_data = data['bytes_data']
result = bytearray(bytes_data) # Create copy
checksum = 0
# Flip each bit
for i in range(size):
byte_idx = i // 8
bit_idx = 7 - (i % 8)
# Get current bit
current_bit = (result[byte_idx] >> bit_idx) & 1
# Flip the bit
if current_bit:
result[byte_idx] &= ~(1 << bit_idx) # Clear bit
else:
result[byte_idx] |= (1 << bit_idx) # Set bit
checksum ^= i
return checksum
@benchmark.implementation("bytes_packed", "flip")
def flip_bytes_packed(data):
"""Flip all boolean values in bytes (bit-packed)"""
# Use bit-packed bytes_data
size = data['size']
bytes_data = data['bytes_data']
result = bytearray(bytes_data) # Convert to mutable
checksum = 0
# Flip each bit
for i in range(size):
byte_idx = i // 8
bit_idx = 7 - (i % 8)
# Get current bit
current_bit = (result[byte_idx] >> bit_idx) & 1
# Flip the bit
if current_bit:
result[byte_idx] &= ~(1 << bit_idx) # Clear bit
else:
result[byte_idx] |= (1 << bit_idx) # Set bit
checksum ^= i
result = bytes(result) # Convert back to immutable
return checksum
# AND operations
@benchmark.implementation("list_bool", "and")
def and_list_bool(data):
"""AND operation on list[bool]"""
lst = data['bool_list']
other = data['other_bool']
checksum = 0
for i in range(len(lst)):
if lst[i] and other[i]:
checksum ^= i
return checksum
@benchmark.implementation("list_int", "and")
def and_list_int(data):
"""AND operation on list[int]"""
lst = data['int_list']
other = data['other_int']
checksum = 0
for i in range(len(lst)):
if lst[i] & other[i]:
checksum ^= i
return checksum
@benchmark.implementation("array_b", "and")
def and_array_b(data):
"""AND operation on array.array('b')"""
arr = data['array_b']
other = array.array('b', data['other_int'])
checksum = 0
for i in range(len(arr)):
if arr[i] & other[i]:
checksum ^= i
return checksum
@benchmark.implementation("array_B", "and")
def and_array_B(data):
"""AND operation on array.array('B')"""
arr = data['array_B']
other = array.array('B', data['other_int'])
checksum = 0
for i in range(len(arr)):
if arr[i] & other[i]:
checksum ^= i
return checksum
@benchmark.implementation("bytearray", "and")
def and_bytearray(data):
"""AND operation on bytearray (non-bit-packed)"""
arr = bytearray(data['int_list'])
other = bytearray(data['other_int'])
checksum = 0
for i in range(len(arr)):
if arr[i] & other[i]:
checksum ^= i
return checksum
@benchmark.implementation("bytes", "and")
def and_bytes(data):
"""AND operation on bytes (non-bit-packed)"""
arr = bytes(data['int_list'])
other = bytes(data['other_int'])
checksum = 0
for i in range(len(arr)):
if arr[i] & other[i]:
checksum ^= i
return checksum
@benchmark.implementation("bytearray_packed", "and")
def and_bytearray_packed(data):
"""AND operation on bytearray (bit-packed)"""
size = data['size']
bytes_data = data['bytes_data']
other_bool = data['other_bool']
checksum = 0
# AND each bit
for i in range(size):
byte_idx = i // 8
bit_idx = 7 - (i % 8)
# Get bits from both arrays
bit1 = (bytes_data[byte_idx] >> bit_idx) & 1
bit2 = other_bool[i]
# AND operation
if bit1 and bit2:
checksum ^= i
return checksum
@benchmark.implementation("bytes_packed", "and")
def and_bytes_packed(data):
"""AND operation on bytes (bit-packed)"""
size = data['size']
bytes_data = data['bytes_data']
other_bool = data['other_bool']
checksum = 0
# AND each bit
for i in range(size):
byte_idx = i // 8
bit_idx = 7 - (i % 8)
# Get bits from both arrays
bit1 = (bytes_data[byte_idx] >> bit_idx) & 1
bit2 = other_bool[i]
# AND operation
if bit1 and bit2:
checksum ^= i
return checksum
# OR operations
@benchmark.implementation("list_bool", "or")
def or_list_bool(data):
"""OR operation on list[bool]"""
lst = data['bool_list']
other = data['other_bool']
checksum = 0
for i in range(len(lst)):
if lst[i] or other[i]:
checksum ^= i
return checksum
@benchmark.implementation("list_int", "or")
def or_list_int(data):
"""OR operation on list[int]"""
lst = data['int_list']
other = data['other_int']
checksum = 0
for i in range(len(lst)):
if lst[i] | other[i]:
checksum ^= i
return checksum
@benchmark.implementation("array_b", "or")
def or_array_b(data):
"""OR operation on array.array('b')"""
arr = data['array_b']
other = array.array('b', data['other_int'])
checksum = 0
for i in range(len(arr)):
if arr[i] | other[i]:
checksum ^= i
return checksum
@benchmark.implementation("array_B", "or")
def or_array_B(data):
"""OR operation on array.array('B')"""
arr = data['array_B']
other = array.array('B', data['other_int'])
checksum = 0
for i in range(len(arr)):
if arr[i] | other[i]:
checksum ^= i
return checksum
@benchmark.implementation("bytearray", "or")
def or_bytearray(data):
"""OR operation on bytearray (non-bit-packed)"""
arr = bytearray(data['int_list'])
other = bytearray(data['other_int'])
checksum = 0
for i in range(len(arr)):
if arr[i] | other[i]:
checksum ^= i
return checksum
@benchmark.implementation("bytes", "or")
def or_bytes(data):
"""OR operation on bytes (non-bit-packed)"""
arr = bytes(data['int_list'])
other = bytes(data['other_int'])
checksum = 0
for i in range(len(arr)):
if arr[i] | other[i]:
checksum ^= i
return checksum
@benchmark.implementation("bytearray_packed", "or")
def or_bytearray_packed(data):
"""OR operation on bytearray (bit-packed)"""
size = data['size']
bytes_data = data['bytes_data']
other_bool = data['other_bool']
checksum = 0
# OR each bit
for i in range(size):
byte_idx = i // 8
bit_idx = 7 - (i % 8)
# Get bits from both arrays
bit1 = (bytes_data[byte_idx] >> bit_idx) & 1
bit2 = other_bool[i]
# OR operation
if bit1 or bit2:
checksum ^= i
return checksum
@benchmark.implementation("bytes_packed", "or")
def or_bytes_packed(data):
"""OR operation on bytes (bit-packed)"""
size = data['size']
bytes_data = data['bytes_data']
other_bool = data['other_bool']
checksum = 0
# OR each bit
for i in range(size):
byte_idx = i // 8
bit_idx = 7 - (i % 8)
# Get bits from both arrays
bit1 = (bytes_data[byte_idx] >> bit_idx) & 1
bit2 = other_bool[i]
# OR operation
if bit1 or bit2:
checksum ^= i
return checksum
# Add bitarray implementations if available
if HAS_BITARRAY:
@benchmark.implementation("bitarray", ["access", "count", "sum", "flip", "and", "or"])
def bitarray_operations(data):
"""Operations on bitarray"""
operation = data['operation']
bit_arr = data['bit_array']
if operation == 'access':
total = 0
access_count = min(1000, len(bit_arr))
step = max(1, len(bit_arr) // access_count)
for i in range(0, len(bit_arr), step):
if i < len(bit_arr) and bit_arr[i]:
total += 1
return total
elif operation == 'count':
return bit_arr.count(True)
elif operation == 'sum':
return bit_arr.count(True)
elif operation == 'flip':
result = bitarray.bitarray(bit_arr)
result.invert()
checksum = 0
for i, bit in enumerate(result):
if bit:
checksum ^= i
return checksum
elif operation == 'and':
other = bitarray.bitarray(data['other_bool'])
result = bit_arr & other
checksum = 0
for i, bit in enumerate(result):
if bit:
checksum ^= i
return checksum
elif operation == 'or':
other = bitarray.bitarray(data['other_bool'])
result = bit_arr | other
checksum = 0
for i, bit in enumerate(result):
if bit:
checksum ^= i
return checksum
# Add custom BitArray implementations if available
if HAS_CUSTOM_BITARRAY:
@benchmark.implementation("custom_bitarray", ["access", "count", "sum"])
def custom_bitarray_operations(data):
"""Operations on custom BitArray"""
operation = data['operation']
bit_arr = data['custom_bitarray']
if operation == 'access':
total = 0
access_count = min(1000, len(bit_arr))
step = max(1, len(bit_arr) // access_count)
for i in range(0, len(bit_arr), step):
if i < len(bit_arr) and bit_arr[i]:
total += 1
return total
elif operation in ['count', 'sum']:
return sum(bit_arr[i] for i in range(len(bit_arr)))
# Custom validator for boolean operations
@benchmark.validator("default")
def validate_bool_result(expected, actual):
"""Validate boolean operation results"""
# Convert results to comparable format
if hasattr(expected, 'tolist'): # array.array
expected = expected.tolist()
if hasattr(actual, 'tolist'): # array.array
actual = actual.tolist()
# Handle bitarray
if hasattr(expected, 'to01'): # bitarray
expected = [int(b) for b in expected.to01()]
if hasattr(actual, 'to01'): # bitarray
actual = [int(b) for b in actual.to01()]
# Convert booleans to ints for comparison
if isinstance(expected, list) and len(expected) > 0:
if isinstance(expected[0], bool):
expected = [int(b) for b in expected]
if isinstance(actual, list) and len(actual) > 0:
if isinstance(actual[0], bool):
actual = [int(b) for b in actual]
return expected == actual
if __name__ == "__main__":
# Parse command line args and run appropriate mode
runner = benchmark.parse_args()
runner.run()
#!/usr/bin/env python3
"""
Simple boolean list benchmark using the new declarative framework.
Compares different boolean data structures and operations.
"""
import random
import array
import sys
import os
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
"""
Declarative benchmark framework with minimal boilerplate.
Features:
- Decorator-based benchmark registration
- Automatic data generation and validation
- Built-in timing with warmup
- Configurable operations and sizes
- JSON results and matplotlib plotting
"""
import time
import json
import statistics
import argparse
from typing import Dict, List, Any, Callable, Union
from dataclasses import dataclass
from pathlib import Path
from collections import defaultdict
@dataclass
class BenchmarkConfig:
"""Configuration for benchmark runs"""
name: str
sizes: List[int] = None
operations: List[str] = None
iterations: int = 10
warmup: int = 2
output_dir: str = "./output/benchmark_results"
save_results: bool = True
plot_results: bool = True
plot_scale: str = "loglog" # Options: "loglog", "linear", "semilogx", "semilogy"
progressive: bool = True # Show results operation by operation across sizes
# Profiling mode
profile_mode: bool = False
profile_size: int = None
profile_operation: str = None
profile_implementation: str = None
def __post_init__(self):
if self.sizes is None:
self.sizes = [100, 1000, 10000, 100000]
if self.operations is None:
self.operations = ['default']
class Benchmark:
"""Declarative benchmark framework using decorators"""
def __init__(self, config: BenchmarkConfig):
self.config = config
self.data_generators = {}
self.implementations = {}
self.validators = {}
self.setups = {}
self.results = []
def profile(self, operation: str = None, size: int = None, implementation: str = None):
"""Create a profiling version of this benchmark"""
profile_config = BenchmarkConfig(
name=f"{self.config.name}_profile",
sizes=self.config.sizes,
operations=self.config.operations,
profile_mode=True,
profile_operation=operation,
profile_size=size,
profile_implementation=implementation,
save_results=False,
plot_results=False
)
profile_benchmark = Benchmark(profile_config)
profile_benchmark.data_generators = self.data_generators
profile_benchmark.implementations = self.implementations
profile_benchmark.validators = self.validators
profile_benchmark.setups = self.setups
return profile_benchmark
def parse_args(self):
"""Parse command line arguments for profiling mode"""
parser = argparse.ArgumentParser(
description=f"Benchmark {self.config.name} with optional profiling mode",
formatter_class=argparse.RawDescriptionHelpFormatter,
epilog="""
Examples:
# Normal benchmark mode
python benchmark.py
# Profile specific operation and implementation
python benchmark.py --profile --operation random_access --implementation grid
# Profile with specific size
python benchmark.py --profile --size 1000000
# Profile all implementations of an operation
python benchmark.py --profile --operation construction
"""
)
parser.add_argument('--profile', action='store_true',
help='Run in profiling mode (minimal overhead for profilers)')
parser.add_argument('--operation', type=str,
help=f'Operation to profile. Options: {", ".join(self.config.operations)}')
parser.add_argument('--size', type=int,
help=f'Size to profile. Options: {", ".join(map(str, self.config.sizes))}')
parser.add_argument('--implementation', type=str,
help='Specific implementation to profile (default: all)')
args = parser.parse_args()
# If profile mode requested, return a profiling benchmark
if args.profile:
return self.profile(
operation=args.operation,
size=args.size,
implementation=args.implementation
)
# Otherwise return self for normal mode
return self
def data_generator(self, name: str = "default"):
"""Decorator to register data generator"""
def decorator(func):
self.data_generators[name] = func
return func
return decorator
def implementation(self, name: str, operations: Union[str, List[str]] = None):
"""Decorator to register implementation"""
if operations is None:
operations = ['default']
elif isinstance(operations, str):
operations = [operations]
def decorator(func):
for op in operations:
if op not in self.implementations:
self.implementations[op] = {}
self.implementations[op][name] = func
return func
return decorator
def validator(self, operation: str = "default"):
"""Decorator to register custom validator"""
def decorator(func):
self.validators[operation] = func
return func
return decorator
def setup(self, name: str, operations: Union[str, List[str]] = None):
"""Decorator to register setup function that runs before timing"""
if operations is None:
operations = ['default']
elif isinstance(operations, str):
operations = [operations]
def decorator(func):
for op in operations:
if op not in self.setups:
self.setups[op] = {}
self.setups[op][name] = func
return func
return decorator
def measure_time(self, func: Callable, data: Any, setup_func: Callable = None) -> tuple[Any, float]:
"""Measure execution time with warmup and optional setup"""
# Warmup runs
for _ in range(self.config.warmup):
try:
if setup_func:
setup_data = setup_func(data)
func(setup_data)
else:
func(data)
except Exception:
# If warmup fails, let the main measurement handle the error
break
# Actual measurement
start = time.perf_counter()
for _ in range(self.config.iterations):
if setup_func:
setup_data = setup_func(data)
result = func(setup_data)
else:
result = func(data)
elapsed_ms = (time.perf_counter() - start) * 1000 / self.config.iterations
return result, elapsed_ms
def validate_result(self, expected: Any, actual: Any, operation: str) -> bool:
"""Validate result using custom validator or default comparison"""
if operation in self.validators:
return self.validators[operation](expected, actual)
return expected == actual
def run(self):
"""Run all benchmarks"""
if self.config.profile_mode:
self._run_profile_mode()
else:
self._run_normal_mode()
def _run_normal_mode(self):
"""Run normal benchmark mode"""
print(f"Running {self.config.name}")
print(f"Sizes: {self.config.sizes}")
print(f"Operations: {self.config.operations}")
print("="*80)
# Always show progressive results: operation by operation across all sizes
for operation in self.config.operations:
for size in self.config.sizes:
self._run_single(operation, size)
# Save and plot results
if self.config.save_results:
self._save_results()
if self.config.plot_results:
self._plot_results()
# Print summary
self._print_summary()
def _run_profile_mode(self):
"""Run profiling mode with minimal overhead for use with vmprof"""
operation = self.config.profile_operation or self.config.operations[0]
size = self.config.profile_size or max(self.config.sizes)
impl_name = self.config.profile_implementation
print(f"PROFILING MODE: {self.config.name}")
print(f"Operation: {operation}, Size: {size}")
if impl_name:
print(f"Implementation: {impl_name}")
print("="*80)
print("Run with vmprof: vmprof --web " + ' '.join(sys.argv))
print("="*80)
# Generate test data
generator = self.data_generators.get(operation, self.data_generators.get('default'))
if not generator:
raise ValueError(f"No data generator for operation: {operation}")
test_data = generator(size, operation)
# Get implementations
impls = self.implementations.get(operation, {})
if not impls:
raise ValueError(f"No implementations for operation: {operation}")
# Filter to specific implementation if requested
if impl_name:
if impl_name not in impls:
raise ValueError(f"Implementation '{impl_name}' not found for operation '{operation}'")
impls = {impl_name: impls[impl_name]}
# Run with minimal overhead - no timing, no validation
for name, func in impls.items():
print(f"\nRunning {name}...")
sys.stdout.flush()
# Setup if needed
setup_func = self.setups.get(operation, {}).get(name)
if setup_func:
data = setup_func(test_data)
else:
data = test_data
# Run the actual function (this is what vmprof will profile)
result = func(data)
print(f"Completed {name}, result checksum: {result}")
sys.stdout.flush()
def _run_single(self, operation: str, size: int):
"""Run a single operation/size combination"""
print(f"\nOperation: {operation}, Size: {size}")
print("-" * 50)
sys.stdout.flush()
# Generate test data
generator = self.data_generators.get(operation,
self.data_generators.get('default'))
if not generator:
raise ValueError(f"No data generator for operation: {operation}")
test_data = generator(size, operation)
# Get implementations for this operation
impls = self.implementations.get(operation, {})
if not impls:
print(f"No implementations for operation: {operation}")
return
# Get setup functions for this operation
setups = self.setups.get(operation, {})
# Run reference implementation first
ref_name, ref_impl = next(iter(impls.items()))
ref_setup = setups.get(ref_name)
expected_result, _ = self.measure_time(ref_impl, test_data, ref_setup)
# Run all implementations
for impl_name, impl_func in impls.items():
try:
setup_func = setups.get(impl_name)
result, time_ms = self.measure_time(impl_func, test_data, setup_func)
correct = self.validate_result(expected_result, result, operation)
# Store result
self.results.append({
'operation': operation,
'size': size,
'implementation': impl_name,
'time_ms': time_ms,
'correct': correct,
'error': None
})
status = "OK" if correct else "FAIL"
print(f" {impl_name:<20} {time_ms:>8.3f} ms {status}")
sys.stdout.flush()
except Exception as e:
self.results.append({
'operation': operation,
'size': size,
'implementation': impl_name,
'time_ms': float('inf'),
'correct': False,
'error': str(e)
})
print(f" {impl_name:<20} ERROR: {str(e)[:40]}")
sys.stdout.flush()
def _save_results(self):
"""Save results to JSON"""
output_dir = Path(self.config.output_dir)
output_dir.mkdir(parents=True, exist_ok=True)
filename = output_dir / f"{self.config.name}_{int(time.time())}.json"
with open(filename, 'w') as f:
json.dump(self.results, f, indent=2)
print(f"\nResults saved to {filename}")
def _plot_results(self):
"""Generate plots using matplotlib if available"""
try:
import matplotlib.pyplot as plt
output_dir = Path(self.config.output_dir)
output_dir.mkdir(parents=True, exist_ok=True)
# Group and prepare data for plotting
data_by_op = self._group_results_by_operation()
# Create plots for each operation
for operation, operation_data in data_by_op.items():
self._create_performance_plot(plt, operation, operation_data, output_dir)
except ImportError:
print("Matplotlib not available - skipping plots")
except Exception as e:
print(f"Plotting failed: {e}")
def _group_results_by_operation(self) -> Dict[str, Dict[int, List[Dict[str, Any]]]]:
"""Group results by operation and size for plotting"""
data_by_op = defaultdict(lambda: defaultdict(list))
for r in self.results:
if r['time_ms'] != float('inf') and r['correct']:
data_by_op[r['operation']][r['size']].append({
'implementation': r['implementation'],
'time_ms': r['time_ms']
})
return data_by_op
def _create_performance_plot(self, plt, operation: str, operation_data: Dict[int, List[Dict[str, Any]]], output_dir: Path):
"""Create a performance plot for a single operation"""
sizes = sorted(operation_data.keys())
implementations = set()
for size_data in operation_data.values():
for entry in size_data:
implementations.add(entry['implementation'])
implementations = sorted(implementations)
plt.figure(figsize=(10, 6))
for impl in implementations:
impl_times = []
impl_sizes = []
for size in sizes:
times = [entry['time_ms'] for entry in operation_data[size]
if entry['implementation'] == impl]
if times:
impl_times.append(statistics.mean(times))
impl_sizes.append(size)
if impl_times:
plt.plot(impl_sizes, impl_times, 'o-', label=impl)
plt.xlabel('Input Size')
plt.ylabel('Time (ms)')
plt.title(f'{self.config.name} - {operation} Operation')
plt.legend()
plt.grid(True, alpha=0.3)
# Apply the configured scaling
if self.config.plot_scale == "loglog":
plt.loglog()
elif self.config.plot_scale == "linear":
pass # Default linear scale
elif self.config.plot_scale == "semilogx":
plt.semilogx()
elif self.config.plot_scale == "semilogy":
plt.semilogy()
else:
# Default to loglog if invalid option
plt.loglog()
plot_file = output_dir / f"{self.config.name}_{operation}_performance.png"
plt.savefig(plot_file, dpi=300, bbox_inches='tight')
plt.close()
print(f"Plot saved: {plot_file}")
def _print_summary(self):
"""Print performance summary"""
print("\n" + "="*80)
print("PERFORMANCE SUMMARY")
print("="*80)
# Group by operation
by_operation = defaultdict(lambda: defaultdict(list))
for r in self.results:
if r['error'] is None and r['time_ms'] != float('inf'):
by_operation[r['operation']][r['implementation']].append(r['time_ms'])
print(f"{'Operation':<15} {'Best Implementation':<20} {'Avg Time (ms)':<15} {'Speedup':<10}")
print("-" * 70)
for op, impl_times in sorted(by_operation.items()):
# Calculate averages
avg_times = [(impl, statistics.mean(times))
for impl, times in impl_times.items()]
avg_times.sort(key=lambda x: x[1])
if avg_times:
best_impl, best_time = avg_times[0]
worst_time = avg_times[-1][1]
speedup = worst_time / best_time if best_time > 0 else 0
print(f"{op:<15} {best_impl:<20} {best_time:<15.3f} {speedup:<10.1f}x")
# Import optional dependencies
try:
import bitarray
HAS_BITARRAY = True
except ImportError:
HAS_BITARRAY = False
try:
'''
╺━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╸
https://kobejean.github.io/cp-library
'''
'''
╺━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╸
https://kobejean.github.io/cp-library
'''
'''
╺━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╸
https://kobejean.github.io/cp-library
'''
class BitArray:
def __init__(B, N):
if isinstance(N, list):
# If N is a list, assume it's a list of 1s and 0s
B.N = len(N)
B.Z = (B.N+31)>>5
B.bits, B.cnt = u32f(B.Z+1), u32f(B.Z+1)
# Set bits based on list values
for i, bit in enumerate(N):
if bit: B.set1(i)
elif isinstance(N, (bytes, bytearray)):
# If N is bytes, convert each byte to 8 bits
B.N = len(N) * 8
B.Z = (B.N+31)>>5
B.bits, B.cnt = u32f(B.Z+1), u32f(B.Z+1)
# Set bits based on byte values (MSB first for each byte)
for byte_idx, byte_val in enumerate(N):
for bit_idx in range(8):
if byte_val & (1 << (7 - bit_idx)): # MSB first
B.set1(byte_idx * 8 + bit_idx)
else:
# Original behavior: N is an integer
B.N = N
B.Z = (N+31)>>5
B.bits, B.cnt = u32f(B.Z+1), u32f(B.Z+1)
def build(B):
B.bits.pop()
for i,b in enumerate(B.bits): B.cnt[i+1] = B.cnt[i]+popcnt32(b)
B.bits.append(1)
def __len__(B): return B.N
def __getitem__(B, i: int): return B.bits[i>>5]>>(31-(i&31))&1
def set0(B, i: int): B.bits[i>>5]&=~(1<<31-(i&31))
def set1(B, i: int): B.bits[i>>5]|=1<<31-(i&31)
def count0(B, r: int): return r-B.count1(r)
def count1(B, r: int): return B.cnt[r>>5]+popcnt32(B.bits[r>>5]>>32-(r&31))
def select0(B, k: int):
if not 0<=k<B.N-B.cnt[-1]: return -1
l,r,k=0,B.N,k+1
while 1<r-l:
if B.count0(m:=(l+r)>>1)<k:l=m
else:r=m
return l
def select1(B, k: int):
if not 0<=k<B.cnt[-1]: return -1
l,r,k=0,B.N,k+1
while 1<r-l:
if B.count1(m:=(l+r)>>1)<k:l=m
else:r=m
return l
'''
╺━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╸
https://kobejean.github.io/cp-library
'''
def popcnt32(x):
x = ((x >> 1) & 0x55555555) + (x & 0x55555555)
x = ((x >> 2) & 0x33333333) + (x & 0x33333333)
x = ((x >> 4) & 0x0f0f0f0f) + (x & 0x0f0f0f0f)
x = ((x >> 8) & 0x00ff00ff) + (x & 0x00ff00ff)
x = ((x >> 16) & 0x0000ffff) + (x & 0x0000ffff)
return x
if hasattr(int, 'bit_count'):
popcnt32 = int.bit_count
'''
╺━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╸
https://kobejean.github.io/cp-library
'''
'''
╺━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╸
https://kobejean.github.io/cp-library
'''
'''
╺━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╸
https://kobejean.github.io/cp-library
'''
from array import array
def u32f(N: int, elm: int = 0): return array('I', (elm,))*N # unsigned int
HAS_CUSTOM_BITARRAY = True
except ImportError:
HAS_CUSTOM_BITARRAY = False
# Configure benchmark
config = BenchmarkConfig(
name="bool_list",
sizes=[1000000, 100000, 10000, 1000, 100, 10, 1], # Reverse order to warm up JIT
operations=['construction', 'access', 'count', 'sum', 'flip', 'and', 'or'],
iterations=10,
warmup=2,
output_dir="./output/benchmark_results/bool_list"
)
# Create benchmark instance
benchmark = Benchmark(config)
# Data generator
@benchmark.data_generator("default")
def generate_bool_data(size: int, operation: str):
"""Generate boolean data in various formats"""
# Generate random boolean data
bool_list = [random.random() < 0.5 for _ in range(size)]
int_list = [int(b) for b in bool_list]
# Create different representations
array_b = array.array('b', int_list)
array_B = array.array('B', int_list)
# Pack into bytes (8 bits per byte)
bytes_data = bytearray((size + 7) // 8)
for i, bit in enumerate(bool_list):
if bit:
bytes_data[i // 8] |= 1 << (7 - (i % 8))
bytes_data = bytes(bytes_data)
# Create bitarray if available
bit_array = None
if HAS_BITARRAY:
bit_array = bitarray.bitarray(bool_list)
# Create custom BitArray if available
custom_bitarray = None
if HAS_CUSTOM_BITARRAY:
custom_bitarray = BitArray(int_list)
custom_bitarray.build()
# Pre-generate auxiliary data for binary operations
other_bool = [random.random() < 0.5 for _ in range(size)]
other_int = [int(b) for b in other_bool]
return {
'bool_list': bool_list,
'int_list': int_list,
'array_b': array_b,
'array_B': array_B,
'bytes_data': bytes_data,
'bit_array': bit_array,
'custom_bitarray': custom_bitarray,
'other_bool': other_bool,
'other_int': other_int,
'size': size,
'operation': operation
}
# Construction operations
@benchmark.implementation("list_bool", "construction")
def construction_list_bool(data):
"""Construct list[bool] from raw data"""
# Use the same source data for all implementations
raw_data = data['bool_list']
result = list(raw_data) # Create a copy
# Return consistent checksum based on source data
checksum = 0
for i, b in enumerate(raw_data):
if b:
checksum ^= i
return checksum
@benchmark.implementation("list_int", "construction")
def construction_list_int(data):
"""Construct list[int] from raw data"""
# Use the same source data for all implementations
raw_data = data['bool_list']
int_list = [int(b) for b in raw_data]
# Return consistent checksum based on source data
checksum = 0
for i, b in enumerate(raw_data):
if b:
checksum ^= i
return checksum
@benchmark.implementation("array_b", "construction")
def construction_array_b(data):
"""Construct array.array('b') from raw data"""
# Use the same source data for all implementations
raw_data = data['bool_list']
int_list = [int(b) for b in raw_data]
array_b = array.array('b', int_list)
# Return consistent checksum based on source data
checksum = 0
for i, b in enumerate(raw_data):
if b:
checksum ^= i
return checksum
@benchmark.implementation("array_B", "construction")
def construction_array_B(data):
"""Construct array.array('B') from raw data"""
# Use the same source data for all implementations
raw_data = data['bool_list']
int_list = [int(b) for b in raw_data]
array_B = array.array('B', int_list)
# Return consistent checksum based on source data
checksum = 0
for i, b in enumerate(raw_data):
if b:
checksum ^= i
return checksum
@benchmark.implementation("bytes", "construction")
def construction_bytes(data):
"""Construct bytes from raw data"""
# Use the same source data for all implementations
raw_data = data['bool_list']
size = data['size']
bytes_data = bytearray((size + 7) // 8)
for i, bit in enumerate(raw_data):
if bit:
bytes_data[i // 8] |= 1 << (7 - (i % 8))
bytes_data = bytes(bytes_data)
# Return consistent checksum based on source data
checksum = 0
for i, b in enumerate(raw_data):
if b:
checksum ^= i
return checksum
if HAS_BITARRAY:
@benchmark.implementation("bitarray", "construction")
def construction_bitarray(data):
"""Construct bitarray from raw data"""
# Use the same source data for all implementations
raw_data = data['bool_list']
bit_array = bitarray.bitarray(raw_data)
# Return consistent checksum based on source data
checksum = 0
for i, b in enumerate(raw_data):
if b:
checksum ^= i
return checksum
if HAS_CUSTOM_BITARRAY:
@benchmark.implementation("custom_bitarray", "construction")
def construction_custom_bitarray(data):
"""Construct custom BitArray from raw data"""
# Use the same source data for all implementations
raw_data = data['bool_list']
int_list = [int(b) for b in raw_data]
custom_bitarray = BitArray(int_list)
custom_bitarray.build()
# Return consistent checksum based on source data
checksum = 0
for i, b in enumerate(raw_data):
if b:
checksum ^= i
return checksum
# Access operations
@benchmark.implementation("list_bool", "access")
def access_list_bool(data):
"""Access operation on list[bool]"""
lst = data['bool_list']
total = 0
access_count = min(1000, len(lst))
step = max(1, len(lst) // access_count)
for i in range(0, len(lst), step):
if i < len(lst) and lst[i]:
total += 1
return total
@benchmark.implementation("list_int", "access")
def access_list_int(data):
"""Access operation on list[int]"""
lst = data['int_list']
total = 0
access_count = min(1000, len(lst))
step = max(1, len(lst) // access_count)
for i in range(0, len(lst), step):
if i < len(lst) and lst[i]:
total += 1
return total
@benchmark.implementation("array_b", "access")
def access_array_b(data):
"""Access operation on array.array('b')"""
arr = data['array_b']
total = 0
access_count = min(1000, len(arr))
step = max(1, len(arr) // access_count)
for i in range(0, len(arr), step):
if i < len(arr) and arr[i]:
total += 1
return total
# Count operations
@benchmark.implementation("list_bool", "count")
def count_list_bool(data):
"""Count True values in list[bool]"""
return data['bool_list'].count(True)
@benchmark.implementation("list_int", "count")
def count_list_int(data):
"""Count True values in list[int]"""
return sum(data['int_list'])
@benchmark.implementation("array_b", "count")
def count_array_b(data):
"""Count True values in array.array('b')"""
return sum(data['array_b'])
# Sum operations (same as count for boolean data)
@benchmark.implementation("list_bool", "sum")
def sum_list_bool(data):
"""Sum boolean values in list[bool]"""
return sum(data['bool_list'])
@benchmark.implementation("list_int", "sum")
def sum_list_int(data):
"""Sum boolean values in list[int]"""
return sum(data['int_list'])
@benchmark.implementation("array_b", "sum")
def sum_array_b(data):
"""Sum boolean values in array.array('b')"""
return sum(data['array_b'])
# Flip operations
@benchmark.implementation("list_bool", "flip")
def flip_list_bool(data):
"""Flip all boolean values in list[bool]"""
lst = list(data['bool_list']) # Create copy
checksum = 0
for i in range(len(lst)):
lst[i] = not lst[i]
if lst[i]:
checksum ^= i
return checksum
@benchmark.implementation("list_int", "flip")
def flip_list_int(data):
"""Flip all boolean values in list[int]"""
lst = list(data['int_list']) # Create copy
checksum = 0
for i in range(len(lst)):
lst[i] = 1 - lst[i]
if lst[i]:
checksum ^= i
return checksum
@benchmark.implementation("array_b", "flip")
def flip_array_b(data):
"""Flip all boolean values in array.array('b')"""
arr = array.array('b', data['array_b']) # Create copy
checksum = 0
for i in range(len(arr)):
arr[i] = 1 - arr[i]
if arr[i]:
checksum ^= i
return checksum
@benchmark.implementation("array_B", "flip")
def flip_array_B(data):
"""Flip all boolean values in array.array('B')"""
arr = array.array('B', data['array_B']) # Create copy
checksum = 0
for i in range(len(arr)):
arr[i] = 1 - arr[i]
if arr[i]:
checksum ^= i
return checksum
@benchmark.implementation("bytearray", "flip")
def flip_bytearray(data):
"""Flip all boolean values in bytearray (non-bit-packed)"""
# Use int_list as source for non-bit-packed
int_list = data['int_list']
result = bytearray(int_list) # Create copy
checksum = 0
for i in range(len(result)):
result[i] = 1 - result[i]
if result[i]:
checksum ^= i
return checksum
@benchmark.implementation("bytes", "flip")
def flip_bytes(data):
"""Flip all boolean values in bytes (non-bit-packed)"""
# Use int_list as source for non-bit-packed
int_list = data['int_list']
result = bytearray(int_list) # Convert to mutable
checksum = 0
for i in range(len(result)):
result[i] = 1 - result[i]
if result[i]:
checksum ^= i
result = bytes(result) # Convert back to immutable
return checksum
@benchmark.implementation("bytearray_packed", "flip")
def flip_bytearray_packed(data):
"""Flip all boolean values in bytearray (bit-packed)"""
# Use bit-packed bytes_data
size = data['size']
bytes_data = data['bytes_data']
result = bytearray(bytes_data) # Create copy
checksum = 0
# Flip each bit
for i in range(size):
byte_idx = i // 8
bit_idx = 7 - (i % 8)
# Get current bit
current_bit = (result[byte_idx] >> bit_idx) & 1
# Flip the bit
if current_bit:
result[byte_idx] &= ~(1 << bit_idx) # Clear bit
else:
result[byte_idx] |= (1 << bit_idx) # Set bit
checksum ^= i
return checksum
@benchmark.implementation("bytes_packed", "flip")
def flip_bytes_packed(data):
"""Flip all boolean values in bytes (bit-packed)"""
# Use bit-packed bytes_data
size = data['size']
bytes_data = data['bytes_data']
result = bytearray(bytes_data) # Convert to mutable
checksum = 0
# Flip each bit
for i in range(size):
byte_idx = i // 8
bit_idx = 7 - (i % 8)
# Get current bit
current_bit = (result[byte_idx] >> bit_idx) & 1
# Flip the bit
if current_bit:
result[byte_idx] &= ~(1 << bit_idx) # Clear bit
else:
result[byte_idx] |= (1 << bit_idx) # Set bit
checksum ^= i
result = bytes(result) # Convert back to immutable
return checksum
# AND operations
@benchmark.implementation("list_bool", "and")
def and_list_bool(data):
"""AND operation on list[bool]"""
lst = data['bool_list']
other = data['other_bool']
checksum = 0
for i in range(len(lst)):
if lst[i] and other[i]:
checksum ^= i
return checksum
@benchmark.implementation("list_int", "and")
def and_list_int(data):
"""AND operation on list[int]"""
lst = data['int_list']
other = data['other_int']
checksum = 0
for i in range(len(lst)):
if lst[i] & other[i]:
checksum ^= i
return checksum
@benchmark.implementation("array_b", "and")
def and_array_b(data):
"""AND operation on array.array('b')"""
arr = data['array_b']
other = array.array('b', data['other_int'])
checksum = 0
for i in range(len(arr)):
if arr[i] & other[i]:
checksum ^= i
return checksum
@benchmark.implementation("array_B", "and")
def and_array_B(data):
"""AND operation on array.array('B')"""
arr = data['array_B']
other = array.array('B', data['other_int'])
checksum = 0
for i in range(len(arr)):
if arr[i] & other[i]:
checksum ^= i
return checksum
@benchmark.implementation("bytearray", "and")
def and_bytearray(data):
"""AND operation on bytearray (non-bit-packed)"""
arr = bytearray(data['int_list'])
other = bytearray(data['other_int'])
checksum = 0
for i in range(len(arr)):
if arr[i] & other[i]:
checksum ^= i
return checksum
@benchmark.implementation("bytes", "and")
def and_bytes(data):
"""AND operation on bytes (non-bit-packed)"""
arr = bytes(data['int_list'])
other = bytes(data['other_int'])
checksum = 0
for i in range(len(arr)):
if arr[i] & other[i]:
checksum ^= i
return checksum
@benchmark.implementation("bytearray_packed", "and")
def and_bytearray_packed(data):
"""AND operation on bytearray (bit-packed)"""
size = data['size']
bytes_data = data['bytes_data']
other_bool = data['other_bool']
checksum = 0
# AND each bit
for i in range(size):
byte_idx = i // 8
bit_idx = 7 - (i % 8)
# Get bits from both arrays
bit1 = (bytes_data[byte_idx] >> bit_idx) & 1
bit2 = other_bool[i]
# AND operation
if bit1 and bit2:
checksum ^= i
return checksum
@benchmark.implementation("bytes_packed", "and")
def and_bytes_packed(data):
"""AND operation on bytes (bit-packed)"""
size = data['size']
bytes_data = data['bytes_data']
other_bool = data['other_bool']
checksum = 0
# AND each bit
for i in range(size):
byte_idx = i // 8
bit_idx = 7 - (i % 8)
# Get bits from both arrays
bit1 = (bytes_data[byte_idx] >> bit_idx) & 1
bit2 = other_bool[i]
# AND operation
if bit1 and bit2:
checksum ^= i
return checksum
# OR operations
@benchmark.implementation("list_bool", "or")
def or_list_bool(data):
"""OR operation on list[bool]"""
lst = data['bool_list']
other = data['other_bool']
checksum = 0
for i in range(len(lst)):
if lst[i] or other[i]:
checksum ^= i
return checksum
@benchmark.implementation("list_int", "or")
def or_list_int(data):
"""OR operation on list[int]"""
lst = data['int_list']
other = data['other_int']
checksum = 0
for i in range(len(lst)):
if lst[i] | other[i]:
checksum ^= i
return checksum
@benchmark.implementation("array_b", "or")
def or_array_b(data):
"""OR operation on array.array('b')"""
arr = data['array_b']
other = array.array('b', data['other_int'])
checksum = 0
for i in range(len(arr)):
if arr[i] | other[i]:
checksum ^= i
return checksum
@benchmark.implementation("array_B", "or")
def or_array_B(data):
"""OR operation on array.array('B')"""
arr = data['array_B']
other = array.array('B', data['other_int'])
checksum = 0
for i in range(len(arr)):
if arr[i] | other[i]:
checksum ^= i
return checksum
@benchmark.implementation("bytearray", "or")
def or_bytearray(data):
"""OR operation on bytearray (non-bit-packed)"""
arr = bytearray(data['int_list'])
other = bytearray(data['other_int'])
checksum = 0
for i in range(len(arr)):
if arr[i] | other[i]:
checksum ^= i
return checksum
@benchmark.implementation("bytes", "or")
def or_bytes(data):
"""OR operation on bytes (non-bit-packed)"""
arr = bytes(data['int_list'])
other = bytes(data['other_int'])
checksum = 0
for i in range(len(arr)):
if arr[i] | other[i]:
checksum ^= i
return checksum
@benchmark.implementation("bytearray_packed", "or")
def or_bytearray_packed(data):
"""OR operation on bytearray (bit-packed)"""
size = data['size']
bytes_data = data['bytes_data']
other_bool = data['other_bool']
checksum = 0
# OR each bit
for i in range(size):
byte_idx = i // 8
bit_idx = 7 - (i % 8)
# Get bits from both arrays
bit1 = (bytes_data[byte_idx] >> bit_idx) & 1
bit2 = other_bool[i]
# OR operation
if bit1 or bit2:
checksum ^= i
return checksum
@benchmark.implementation("bytes_packed", "or")
def or_bytes_packed(data):
"""OR operation on bytes (bit-packed)"""
size = data['size']
bytes_data = data['bytes_data']
other_bool = data['other_bool']
checksum = 0
# OR each bit
for i in range(size):
byte_idx = i // 8
bit_idx = 7 - (i % 8)
# Get bits from both arrays
bit1 = (bytes_data[byte_idx] >> bit_idx) & 1
bit2 = other_bool[i]
# OR operation
if bit1 or bit2:
checksum ^= i
return checksum
# Add bitarray implementations if available
if HAS_BITARRAY:
@benchmark.implementation("bitarray", ["access", "count", "sum", "flip", "and", "or"])
def bitarray_operations(data):
"""Operations on bitarray"""
operation = data['operation']
bit_arr = data['bit_array']
if operation == 'access':
total = 0
access_count = min(1000, len(bit_arr))
step = max(1, len(bit_arr) // access_count)
for i in range(0, len(bit_arr), step):
if i < len(bit_arr) and bit_arr[i]:
total += 1
return total
elif operation == 'count':
return bit_arr.count(True)
elif operation == 'sum':
return bit_arr.count(True)
elif operation == 'flip':
result = bitarray.bitarray(bit_arr)
result.invert()
checksum = 0
for i, bit in enumerate(result):
if bit:
checksum ^= i
return checksum
elif operation == 'and':
other = bitarray.bitarray(data['other_bool'])
result = bit_arr & other
checksum = 0
for i, bit in enumerate(result):
if bit:
checksum ^= i
return checksum
elif operation == 'or':
other = bitarray.bitarray(data['other_bool'])
result = bit_arr | other
checksum = 0
for i, bit in enumerate(result):
if bit:
checksum ^= i
return checksum
# Add custom BitArray implementations if available
if HAS_CUSTOM_BITARRAY:
@benchmark.implementation("custom_bitarray", ["access", "count", "sum"])
def custom_bitarray_operations(data):
"""Operations on custom BitArray"""
operation = data['operation']
bit_arr = data['custom_bitarray']
if operation == 'access':
total = 0
access_count = min(1000, len(bit_arr))
step = max(1, len(bit_arr) // access_count)
for i in range(0, len(bit_arr), step):
if i < len(bit_arr) and bit_arr[i]:
total += 1
return total
elif operation in ['count', 'sum']:
return sum(bit_arr[i] for i in range(len(bit_arr)))
# Custom validator for boolean operations
@benchmark.validator("default")
def validate_bool_result(expected, actual):
"""Validate boolean operation results"""
# Convert results to comparable format
if hasattr(expected, 'tolist'): # array.array
expected = expected.tolist()
if hasattr(actual, 'tolist'): # array.array
actual = actual.tolist()
# Handle bitarray
if hasattr(expected, 'to01'): # bitarray
expected = [int(b) for b in expected.to01()]
if hasattr(actual, 'to01'): # bitarray
actual = [int(b) for b in actual.to01()]
# Convert booleans to ints for comparison
if isinstance(expected, list) and len(expected) > 0:
if isinstance(expected[0], bool):
expected = [int(b) for b in expected]
if isinstance(actual, list) and len(actual) > 0:
if isinstance(actual[0], bool):
actual = [int(b) for b in actual]
return expected == actual
if __name__ == "__main__":
# Parse command line args and run appropriate mode
runner = benchmark.parse_args()
runner.run()