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())