Skip to content

Instantly share code, notes, and snippets.

@misrasaurabh1
Last active July 31, 2025 06:17
Show Gist options
  • Select an option

  • Save misrasaurabh1/5d860435ebdd2d94d3a987b906a08bba to your computer and use it in GitHub Desktop.

Select an option

Save misrasaurabh1/5d860435ebdd2d94d3a987b906a08bba to your computer and use it in GitHub Desktop.
#!/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()
@misrasaurabh1
Copy link
Copy Markdown
Author

Creating test object...

Benchmarking copy methods on object with 5000 items
Estimated object size: ~0.00 MB
--------------------------------------------------
Method          | Time     | Status
--------------------------------------------------
shallow_copy    |   0.0000s | ✓
deepcopy        |   0.0090s | ✓
json_copy       |   0.0068s | ✓
pickle_copy     |   0.0020s | ✓
orjson_copy     |   0.0014s | ✓
--------------------------------------------------

Fastest method: shallow_copy (0.0000s)

Relative performance:
  shallow_copy   :  1.00x slower
  orjson_copy    : 100.19x slower
  pickle_copy    : 146.97x slower
  json_copy      : 504.14x slower
  deepcopy       : 664.24x slower

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment