196 lines
5.7 KiB
Python
196 lines
5.7 KiB
Python
import gc
|
|
import json
|
|
import os
|
|
import random
|
|
import secrets
|
|
import shutil
|
|
import tempfile
|
|
import time
|
|
from unittest.mock import MagicMock
|
|
|
|
import psutil
|
|
|
|
from meshchatx.src.backend.database import Database
|
|
|
|
|
|
def get_memory_usage():
|
|
"""Returns current process memory usage in MB."""
|
|
process = psutil.Process(os.getpid())
|
|
return process.memory_info().rss / (1024 * 1024)
|
|
|
|
|
|
def generate_hash():
|
|
return secrets.token_hex(16)
|
|
|
|
|
|
class MapBenchmarker:
|
|
def __init__(self):
|
|
self.results = []
|
|
self.temp_dir = tempfile.mkdtemp()
|
|
self.db_path = os.path.join(self.temp_dir, "map_perf_test.db")
|
|
self.db = Database(self.db_path)
|
|
self.db.initialize()
|
|
self.identity_hash = generate_hash()
|
|
|
|
def cleanup(self):
|
|
self.db.close()
|
|
shutil.rmtree(self.temp_dir)
|
|
|
|
def record_benchmark(self, name, operation, iterations=1):
|
|
gc.collect()
|
|
start_mem = get_memory_usage()
|
|
start_time = time.time()
|
|
|
|
operation()
|
|
|
|
end_time = time.time()
|
|
gc.collect()
|
|
end_mem = get_memory_usage()
|
|
|
|
duration = (end_time - start_time) / iterations
|
|
mem_diff = end_mem - start_mem
|
|
|
|
result = {
|
|
"name": name,
|
|
"duration_ms": duration * 1000,
|
|
"memory_growth_mb": mem_diff,
|
|
"iterations": iterations,
|
|
}
|
|
self.results.append(result)
|
|
print(f"Benchmark: {name}")
|
|
print(f" Avg Duration: {result['duration_ms']:.2f} ms")
|
|
print(f" Memory Growth: {result['memory_growth_mb']:.2f} MB")
|
|
return result
|
|
|
|
def benchmark_telemetry_insertion(self, count=1000):
|
|
def run_telemetry():
|
|
with self.db.provider:
|
|
for i in range(count):
|
|
self.db.telemetry.upsert_telemetry(
|
|
destination_hash=generate_hash(),
|
|
timestamp=time.time(),
|
|
data=os.urandom(100), # simulate packed telemetry
|
|
received_from=generate_hash(),
|
|
)
|
|
|
|
self.record_benchmark(
|
|
f"Telemetry Insertion ({count} entries)",
|
|
run_telemetry,
|
|
count,
|
|
)
|
|
|
|
def benchmark_telemetry_retrieval(self, count=100):
|
|
# Seed some data first
|
|
dest_hash = generate_hash()
|
|
for i in range(500):
|
|
self.db.telemetry.upsert_telemetry(
|
|
destination_hash=dest_hash,
|
|
timestamp=time.time() - i,
|
|
data=os.urandom(100),
|
|
)
|
|
|
|
def run_retrieval():
|
|
for _ in range(count):
|
|
self.db.telemetry.get_telemetry_history(dest_hash, limit=100)
|
|
|
|
self.record_benchmark(
|
|
f"Telemetry History Retrieval ({count} calls)",
|
|
run_retrieval,
|
|
count,
|
|
)
|
|
|
|
def benchmark_drawing_storage(self, count=500):
|
|
# Create a large GeoJSON-like string
|
|
dummy_data = json.dumps(
|
|
{
|
|
"type": "FeatureCollection",
|
|
"features": [
|
|
{
|
|
"type": "Feature",
|
|
"geometry": {
|
|
"type": "Point",
|
|
"coordinates": [
|
|
random.uniform(-180, 180),
|
|
random.uniform(-90, 90),
|
|
],
|
|
},
|
|
"properties": {"name": f"Marker {i}"},
|
|
}
|
|
for i in range(100)
|
|
],
|
|
},
|
|
)
|
|
|
|
def run_drawings():
|
|
with self.db.provider:
|
|
for i in range(count):
|
|
self.db.map_drawings.upsert_drawing(
|
|
identity_hash=self.identity_hash,
|
|
name=f"Layer {i}",
|
|
data=dummy_data,
|
|
)
|
|
|
|
self.record_benchmark(
|
|
f"Map Drawing Insertion ({count} layers)",
|
|
run_drawings,
|
|
count,
|
|
)
|
|
|
|
def benchmark_drawing_listing(self, count=100):
|
|
def run_list():
|
|
for _ in range(count):
|
|
self.db.map_drawings.get_drawings(self.identity_hash)
|
|
|
|
self.record_benchmark(f"Map Drawing Listing ({count} calls)", run_list, count)
|
|
|
|
def benchmark_mbtiles_listing(self, count=100):
|
|
from meshchatx.src.backend.map_manager import MapManager
|
|
|
|
# Mock config
|
|
config = MagicMock()
|
|
config.map_mbtiles_dir.get.return_value = self.temp_dir
|
|
|
|
# Create some dummy .mbtiles files
|
|
for i in range(5):
|
|
with open(os.path.join(self.temp_dir, f"test_{i}.mbtiles"), "w") as f:
|
|
f.write("dummy")
|
|
|
|
mm = MapManager(config, self.temp_dir)
|
|
|
|
def run_list():
|
|
for _ in range(count):
|
|
mm.list_mbtiles()
|
|
|
|
self.record_benchmark(
|
|
f"MBTiles Listing ({count} calls, 5 files)",
|
|
run_list,
|
|
count,
|
|
)
|
|
|
|
|
|
def main():
|
|
print("Starting Map-related Performance Benchmarking...")
|
|
bench = MapBenchmarker()
|
|
try:
|
|
bench.benchmark_telemetry_insertion(1000)
|
|
bench.benchmark_telemetry_retrieval(100)
|
|
bench.benchmark_drawing_storage(500)
|
|
bench.benchmark_drawing_listing(100)
|
|
bench.benchmark_mbtiles_listing(100)
|
|
|
|
print("\n" + "=" * 80)
|
|
print(f"{'Benchmark Name':40} | {'Avg Time':10} | {'Mem Growth':10}")
|
|
print("-" * 80)
|
|
for r in bench.results:
|
|
print(
|
|
f"{r['name']:40} | {r['duration_ms']:8.2f} ms | {r['memory_growth_mb']:8.2f} MB",
|
|
)
|
|
print("=" * 80)
|
|
|
|
finally:
|
|
bench.cleanup()
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|