httpd: remove memory profiling code

Remove objgraph/pympler imports, gc.get_objects() caching,
and memory_samples tracking. Keep basic RSS tracking for dashboard.
This commit is contained in:
Username
2026-01-17 19:25:33 +01:00
parent 12174b0d9d
commit d87ff73d95

117
httpd.py
View File

@@ -58,32 +58,14 @@ _LIB_CACHE = {}
# Cache for dashboard static files (HTML, CSS, JS)
_STATIC_CACHE = {}
# Optional memory profiling (installed via requirements.txt)
try:
import objgraph
_has_objgraph = True
except ImportError:
_has_objgraph = False
try:
from pympler import muppy, summary
_has_pympler = True
except ImportError:
_has_pympler = False
# Memory tracking for leak detection
_memory_samples = []
_memory_sample_max = 60 # Keep last 60 samples (5 min at 5s intervals)
_peak_rss = 0
_start_rss = 0
# Cache for expensive operations
_gc_objects_cache = {'value': 0, 'time': 0}
_gc_objects_ttl = 30 # seconds
_db_health_cache = {'value': {}, 'time': 0}
_db_health_ttl = 10 # seconds
# Simple RSS tracking for dashboard
_peak_rss = 0
_start_rss = 0
# Worker registry for distributed testing
import hashlib
import random
@@ -669,39 +651,26 @@ def get_system_stats():
stats['proc_rss'] = 0
stats['proc_threads'] = 0
# Memory leak detection
global _memory_samples, _peak_rss, _start_rss
# Simple RSS tracking for dashboard
global _peak_rss, _start_rss
rss = stats.get('proc_rss', 0)
if rss > 0:
if _start_rss == 0:
_start_rss = rss
if rss > _peak_rss:
_peak_rss = rss
_memory_samples.append((time.time(), rss))
if len(_memory_samples) > _memory_sample_max:
_memory_samples.pop(0)
stats['proc_rss_peak'] = _peak_rss
stats['proc_rss_start'] = _start_rss
stats['proc_rss_growth'] = rss - _start_rss if _start_rss > 0 else 0
# GC stats for leak detection
# GC generation counts (fast - no object iteration)
try:
gc_counts = gc.get_count()
stats['gc_count_gen0'] = gc_counts[0]
stats['gc_count_gen1'] = gc_counts[1]
stats['gc_count_gen2'] = gc_counts[2]
# Cache gc.get_objects() - expensive call (~23ms)
global _gc_objects_cache
now = time.time()
if now - _gc_objects_cache['time'] > _gc_objects_ttl:
_gc_objects_cache['value'] = len(gc.get_objects())
_gc_objects_cache['time'] = now
stats['gc_objects'] = _gc_objects_cache['value']
except Exception as e:
_log('gc stats error: %s' % e, 'debug')
except Exception:
stats['gc_count_gen0'] = stats['gc_count_gen1'] = stats['gc_count_gen2'] = 0
stats['gc_objects'] = 0
return stats
@@ -1438,76 +1407,6 @@ class ProxyAPIServer(threading.Thread):
return json.dumps({'count': row[0] if row else 0}), 'application/json', 200
except Exception as e:
return json.dumps({'error': str(e)}), 'application/json', 500
elif path == '/api/memory':
# Memory profiling endpoint (localhost only)
if not is_localhost(remote_addr):
return json.dumps({'error': 'not available'}), 'application/json', 404
try:
mem = {}
# Process memory from /proc/self/status
try:
with open('/proc/self/status', 'r') as f:
for line in f:
if line.startswith('Vm'):
parts = line.split()
key = parts[0].rstrip(':')
mem[key] = int(parts[1]) * 1024 # Convert to bytes
except IOError:
pass
# GC stats
gc_stats = {
'collections': gc.get_count(),
'threshold': gc.get_threshold(),
'objects': len(gc.get_objects()),
}
# Object type counts (top 20)
type_counts = {}
for obj in gc.get_objects():
t = type(obj).__name__
type_counts[t] = type_counts.get(t, 0) + 1
top_types = sorted(type_counts.items(), key=lambda x: -x[1])[:20]
# Memory samples history
samples = []
for ts, rss in _memory_samples[-30:]:
samples.append({'time': int(ts), 'rss': rss})
result = {
'process': mem,
'gc': gc_stats,
'top_types': [{'type': t, 'count': c} for t, c in top_types],
'samples': samples,
'peak_rss': _peak_rss,
'start_rss': _start_rss,
'has_objgraph': _has_objgraph,
'has_pympler': _has_pympler,
}
# Objgraph most common types (if available)
if _has_objgraph:
try:
result['objgraph_common'] = objgraph.most_common_types(limit=15)
except Exception as e:
result['objgraph_error'] = str(e)
# Pympler summary (if available)
if _has_pympler:
try:
all_objects = muppy.get_objects()
sum_table = summary.summarize(all_objects)
result['pympler_summary'] = [
{'type': row[0], 'count': row[1], 'size': row[2]}
for row in sum_table[:20]
]
except Exception as e:
result['pympler_error'] = str(e)
return json.dumps(result, indent=2), 'application/json', 200
except Exception as e:
return json.dumps({'error': str(e)}), 'application/json', 500
elif path == '/health':
return json.dumps({'status': 'ok', 'version': __version__, 'timestamp': int(time.time())}), 'application/json', 200