Last active
July 31, 2025 06:17
-
-
Save misrasaurabh1/5d860435ebdd2d94d3a987b906a08bba to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/usr/bin/env python3 | |
| """ | |
| Benchmark script to compare performance of different Python object copying methods. | |
| """ | |
| import copy | |
| import json | |
| import pickle | |
| import time | |
| import sys | |
| from typing import Dict, List, Any, Tuple | |
| try: | |
| import orjson | |
| HAS_ORJSON = True | |
| except ImportError: | |
| HAS_ORJSON = False | |
| print("Warning: orjson not installed, skipping orjson tests") | |
| class ComplexObject: | |
| """A complex object with nested data structures to test copying performance.""" | |
| def __init__(self, size: int = 5000): | |
| self.size = size | |
| self.data = self._generate_complex_data() | |
| def _generate_complex_data(self) -> Dict[str, Any]: | |
| """Generate a complex nested data structure.""" | |
| if self.size == 0: | |
| return {} | |
| return { | |
| 'strings': [f'string_{i}' for i in range(self.size)], | |
| 'numbers': list(range(self.size)), | |
| 'floats': [i * 0.1 for i in range(self.size)], | |
| 'nested_dicts': [ | |
| { | |
| 'id': i, | |
| 'name': f'item_{i}', | |
| 'metadata': { | |
| 'created': f'2023-01-{i % 28 + 1:02d}', | |
| 'tags': [f'tag_{j}' for j in range(i % 10)], | |
| 'scores': [j * 0.5 for j in range(i % 20)] | |
| } | |
| } for i in range(self.size // 10) | |
| ], | |
| 'matrix': [[i * j for j in range(50)] for i in range(50)], | |
| 'boolean_flags': [i % 2 == 0 for i in range(self.size)], | |
| 'mixed_list': [ | |
| 'string', 42, 3.14, True, None, | |
| {'nested': [1, 2, 3]}, | |
| [4, 5, 6] | |
| ] * (self.size // 100), | |
| } | |
| def create_test_object(size: int = 5000) -> ComplexObject: | |
| """Create a large test object for benchmarking.""" | |
| return ComplexObject(size) | |
| def test_deepcopy(obj: ComplexObject) -> ComplexObject: | |
| """Test copy.deepcopy performance.""" | |
| return copy.deepcopy(obj) | |
| def test_shallow_copy(obj: ComplexObject) -> ComplexObject: | |
| """Test copy.copy performance.""" | |
| return copy.copy(obj) | |
| def test_json_copy(obj: ComplexObject) -> ComplexObject: | |
| """Test json.loads(json.dumps()) performance.""" | |
| json_str = json.dumps(obj.data) | |
| new_data = json.loads(json_str) | |
| new_obj = ComplexObject(0) | |
| new_obj.data = new_data | |
| new_obj.size = obj.size | |
| return new_obj | |
| def test_orjson_copy(obj: ComplexObject) -> ComplexObject: | |
| """Test orjson.loads(orjson.dumps()) performance.""" | |
| json_bytes = orjson.dumps(obj.data) | |
| new_data = orjson.loads(json_bytes) | |
| new_obj = ComplexObject(0) | |
| new_obj.data = new_data | |
| new_obj.size = obj.size | |
| return new_obj | |
| def test_pickle_copy(obj: ComplexObject) -> ComplexObject: | |
| """Test pickle.loads(pickle.dumps()) performance.""" | |
| return pickle.loads(pickle.dumps(obj)) | |
| def measure_copy_method(method_func, obj: ComplexObject, method_name: str) -> Tuple[float, bool]: | |
| """Measure the performance of a copy method.""" | |
| try: | |
| start_time = time.perf_counter() | |
| result = method_func(obj) | |
| end_time = time.perf_counter() | |
| elapsed = end_time - start_time | |
| success = result is not None | |
| print(f"{method_name:15} | {elapsed:8.4f}s | {'✓' if success else '✗'}") | |
| return elapsed, success | |
| except Exception as e: | |
| print(f"{method_name:15} | {'ERROR':8} | ✗ - {str(e)[:50]}") | |
| return float('inf'), False | |
| def run_benchmark(): | |
| """Run the complete benchmark suite.""" | |
| print("Creating test object...") | |
| test_obj = create_test_object(5000) | |
| print(f"\nBenchmarking copy methods on object with {test_obj.size} items") | |
| print(f"Estimated object size: ~{sys.getsizeof(test_obj.data) / 1024 / 1024:.2f} MB") | |
| print("-" * 50) | |
| print(f"{'Method':15} | {'Time':8} | Status") | |
| print("-" * 50) | |
| methods = [ | |
| (test_shallow_copy, "shallow_copy"), | |
| (test_deepcopy, "deepcopy"), | |
| (test_json_copy, "json_copy"), | |
| (test_pickle_copy, "pickle_copy"), | |
| ] | |
| if HAS_ORJSON: | |
| methods.append((test_orjson_copy, "orjson_copy")) | |
| results = {} | |
| for method_func, method_name in methods: | |
| elapsed, success = measure_copy_method(method_func, test_obj, method_name) | |
| if success: | |
| results[method_name] = elapsed | |
| print("-" * 50) | |
| if results: | |
| fastest_method = min(results.keys(), key=lambda k: results[k]) | |
| print(f"\nFastest method: {fastest_method} ({results[fastest_method]:.4f}s)") | |
| print("\nRelative performance:") | |
| baseline = results[fastest_method] | |
| for method, time_taken in sorted(results.items(), key=lambda x: x[1]): | |
| relative = time_taken / baseline | |
| print(f" {method:15}: {relative:5.2f}x slower") | |
| if __name__ == "__main__": | |
| run_benchmark() |
Author
misrasaurabh1
commented
Jul 31, 2025
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment