Jedes Mal, wenn Sie eine Anwendung mit einem leistungsintensiven kritischen Pfad haben, sollten Sie sich Gedanken darüber machen, wie Sie mit dem Speicher umgehen. Die meisten clientseitigen Endbenutzeranwendungen fallen nicht in diese Kategorie, da sie primär ereignisgesteuert sind und die meisten Ereignisse aus Interaktionen mit dem Benutzer stammen und nicht so viele (wenn überhaupt) Leistungseinschränkungen bestehen.
Viele Back-End-Programme sollten sich jedoch darauf konzentrieren, wie der Speicher behandelt wird, da viele dieser Software skaliert werden können, um eine höhere Anzahl von Clients, eine größere Anzahl von Transaktionen und mehr Datenquellen zu verarbeiten. Sobald Sie beginnen Wenn Sie die Grenzen überschreiten, können Sie mit der Analyse des Arbeitsspeichers Ihrer Softwarebenutzer beginnen und benutzerdefinierte Zuordnungsschemata schreiben, die auf Ihre Software zugeschnitten sind, anstatt sich auf einen vollständig generischen Speicherzuweiser zu verlassen, der für jeden denkbaren Anwendungsfall geschrieben wurde.
Um nur einige Beispiele zu nennen ... In meiner ersten Firma habe ich an einem Historian-Paket gearbeitet, einer Software, die für das Sammeln / Speichern / Archivieren von Prozesssteuerungsdaten verantwortlich ist (denken Sie an eine Fabrik, ein Kernkraftwerk oder eine Ölraffinerie mit 10 Millionen Sensoren). wir würden diese Daten speichern). Jedes Mal, wenn wir einen Leistungsengpass analysierten, der den Historian daran hinderte, mehr Daten zu verarbeiten, lag das Problem meistens darin, wie der Speicher behandelt wurde. Wir haben große Anstrengungen unternommen, um sicherzustellen, dass malloc / free nicht aufgerufen wurden, es sei denn, sie waren absolut notwendig.
In meinem aktuellen Job arbeite ich an einem digitalen Überwachungsvideorecorder und einem Analysepaket. Bei 30 fps empfängt jeder Kanal alle 33 Millisekunden ein Videobild. Auf der von uns verkauften Hardware können wir problemlos 100 Videokanäle aufnehmen. Dies ist also ein weiterer Fall, um sicherzustellen, dass im kritischen Pfad (Netzwerkaufruf => Erfassungskomponenten => Rekorderverwaltungssoftware => Speicherkomponenten => Festplatte) keine dynamischen Speicherzuordnungen vorhanden sind. Wir haben einen benutzerdefinierten Frame-Allokator, der Puffer mit hoher Größe enthält und LIFO verwendet, um zuvor zugewiesene Puffer wiederzuverwenden. Wenn Sie 600 KB Speicher benötigen, erhalten Sie möglicherweise 1024 KB Puffer, der Speicherplatz verschwendet. Da dieser Speicher jedoch speziell auf unsere Verwendung zugeschnitten ist, bei der jede Zuordnung nur von kurzer Dauer ist, funktioniert er sehr gut, da der Puffer verwendet wird.
Bei der von mir beschriebenen Art von Anwendungen (Verschieben vieler Daten von A nach B und Behandeln einer großen Anzahl von Clientanforderungen) ist das Hin- und Herbewegen auf den Heap und zurück eine Hauptursache für CPU-Leistungsengpässe. Das Reduzieren der Heap-Fragmentierung auf ein Minimum ist ein sekundärer Vorteil. Soweit ich jedoch feststellen kann, implementieren die meisten modernen Betriebssysteme bereits Heaps mit geringer Fragmentierung (zumindest weiß ich, dass Windows dies tut, und ich würde hoffen, dass dies auch andere tun). Persönlich habe ich in mehr als 12 Jahren in solchen Umgebungen Probleme mit der CPU-Auslastung im Zusammenhang mit Heap gesehen, während ich noch nie ein System gesehen habe, das tatsächlich unter fragmentiertem Heap gelitten hat.