forked from hofmannol/AlgoDatSoSe25
149 lines
3.9 KiB
Python
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())
|
|
|