AlgoDatSoSe25/utils/memory_manager.py
2025-04-07 11:58:13 +02:00

149 lines
3.9 KiB
Python

import matplotlib.pyplot as plt
import queue
class MemoryManager:
_instance = None
stats = {}
def __new__(cls, *args, **kwargs):
"""Erstellt eine einzige Instanz von MemoryManager."""
if cls._instance is None:
cls._instance = super().__new__(cls)
cls._instance._initialize() # Eigene Init-Methode, damit __init__ nicht mehrfach läuft
return cls._instance
def _initialize(self):
"""Initialisiert die Speicherverwaltung (einmalig)."""
self.cells = []
self._pool = queue.Queue()
self._finalizers = {}
@staticmethod
def count_cells():
return len(MemoryManager().cells)
@staticmethod
def count_reads():
return sum([cell.read_count for cell in MemoryManager().cells])
@staticmethod
def count_writes():
return sum([cell.write_count for cell in MemoryManager().cells])
@staticmethod
def count_compares():
return sum([cell.compare_count for cell in MemoryManager().cells])
@staticmethod
def count_adds():
return sum([cell.add_count for cell in MemoryManager().cells])
@staticmethod
def count_subs():
return sum([cell.sub_count for cell in MemoryManager().cells])
@staticmethod
def count_muls():
return sum([cell.mul_count for cell in MemoryManager().cells])
@staticmethod
def count_divs():
return sum([cell.div_count for cell in MemoryManager().cells])
@staticmethod
def count_bitops():
return sum([cell.bitop_count for cell in MemoryManager().cells])
@staticmethod
def reset():
manager = MemoryManager()
for cell in manager.cells:
cell.reset_counters()
@staticmethod
def purge():
MemoryManager._instance = None
@staticmethod
def save_stats(count):
data = { "cells": MemoryManager.count_cells(),
"reads": MemoryManager.count_reads(),
"writes": MemoryManager.count_writes(),
"compares": MemoryManager.count_compares(),
"adds": MemoryManager.count_adds(),
"subs": MemoryManager.count_subs(),
"muls": MemoryManager.count_muls(),
"divs": MemoryManager.count_divs(),
"bitops": MemoryManager.count_bitops() }
MemoryManager.stats[count] = data
@staticmethod
def plot_stats(labels):
data = MemoryManager.stats
x = list(data.keys())
fig, axes = plt.subplots(len(labels), 1, figsize=(8, 4 * len(labels)), sharex=True)
if len(labels) == 1:
axes = [axes] # Falls nur ein Plot vorhanden ist, in eine Liste umwandeln
for ax, l in zip(axes, labels):
y = [data[k][l] for k in x]
ax.plot(x, y, label=l)
ax.set_ylabel(l)
ax.legend()
plt.xlabel("n")
plt.show()
def acquire_cell(self):
try:
return self._pool.get_nowait()
except queue.Empty:
return None
def register_cell(self, cell):
self.cells.append(cell)
def release_cell(self, cell):
self._pool.put(cell)
class Testcell:
def __new__(cls, *args, **kwargs):
instance = MemoryManager().acquire_cell()
if instance is None:
instance = super().__new__(cls)
MemoryManager().register_cell(instance)
return instance
def __enter__(self):
return self
def __exit__(self, exc_type, exc_val, exc_tb):
MemoryManager().release_cell(self)
if __name__ == "__main__":
# Einfaches Anlegen einer Zelle
a = Testcell()
print(MemoryManager.count_cells())
# Anlegen einer Zelle und Beenden des Scopes
with Testcell() as b:
print(MemoryManager.count_cells())
print(MemoryManager.count_cells())
# Reuse einer Zelle
c = Testcell()
print(MemoryManager.count_cells())