Wird die Speicherverwaltung beim Programmieren zu einem irrelevanten Problem?

38

Hintergrund
Ich habe eine alte (aber großartige) Website erneut besucht, auf der ich lange nicht mehr war - das Alioth Language Shootout ( http://benchmarksgame.alioth.debian.org/ ).

Ich habe vor einigen Jahren mit dem Programmieren in C / C ++ begonnen, arbeite seitdem jedoch aufgrund von Sprachbeschränkungen in den Projekten, an denen ich beteiligt war, fast ausschließlich in Java. Da ich mich nicht an die Zahlen erinnere, wollte ich ungefähr sehen, wie gut Java ist in Bezug auf die Ressourcennutzung gegen C / C ++ abgeschlagen.

Die Ausführungszeiten waren immer noch relativ gut, wobei Java im schlechtesten Fall 4x langsamer lief als C / C ++, aber im Durchschnitt bei 2x (oder darunter). Aufgrund der Art der Implementierung von Java selbst war dies keine Überraschung, und die Performance-Zeit war tatsächlich geringer als erwartet.

Der eigentliche Baustein war die Speicherzuweisung - im schlimmsten Fall hat Java Folgendes zugewiesen:

  • satte 52x mehr Speicher als C
  • und 25x mehr als C ++.

52x die Erinnerung ... Absolut böse, oder? ... oder ist es? Speicher ist jetzt vergleichsweise billig.

Frage:
Wenn wir nicht in Bezug auf Zielplattformen mit strengen Einschränkungen des Arbeitsspeichers (dh eingebettete Systeme und dergleichen) sprechen, sollte die Speichernutzung heute ein Problem bei der Auswahl einer Allzwecksprache sein?

Ich frage zum Teil, weil ich erwäge, zu Scala als meine Hauptsprache zu migrieren. Ich mag die funktionalen Aspekte sehr, aber soweit ich das sehe, ist es in Bezug auf den Speicher sogar noch teurer als Java. Da der Speicher jedoch von Jahr zu Jahr schneller, billiger und umfangreicher zu werden scheint (es scheint immer schwieriger zu werden, einen Consumer-Laptop ohne mindestens 4 GB DDR3-RAM zu finden), kann nicht argumentiert werden, dass das Ressourcenmanagement immer umfangreicher wird irrelevant im Vergleich zu (möglicherweise in Bezug auf die Implementierung teuren) Hochsprachenfunktionen, die eine schnellere Erstellung besser lesbarer Lösungen ermöglichen?

csvan
quelle
32
Vergessen Sie nicht, dass Java, nur weil es für einen kleinen Benchmark 52x mehr Speicher als C reserviert, für eine große Anwendung nicht 52x mehr Speicher benötigt. Der Löwenanteil dieses Speichers ist ein fester Betrag, der von der JVM benötigt wird. Je größer Ihre Anwendung wird, desto geringer wird die Bedeutung dieses Teils.
Carson63000
4
Wenn mobile Entwicklung keine Rolle spielt, dann ja.
JeffO
3
Die Frage ist, wie schlecht der Java-Benchmark im Vergleich zu C / C ++ ist und was dies für die Auswahl zwischen den beiden Sprachen bedeutet. Ich sehe dies als themenbezogen, für alle Programmierer relevant, klar, fokussiert und in der aktuellen Form angemessen zu beantworten. Ich habe für die Wiedereröffnung gestimmt.
GlenPeterson
Die meisten Leistungsprobleme werden auf Designebene und nicht auf Toolebene verursacht und behoben. Einige Probleme benötigen eine Granularität von 1 ms und erfordern daher C / C ++. Wenn Sie Spielraum haben, wie 10 ms, dann ist Scala oder Java vielleicht eine gute Option. Die meisten Eingabecontroller für Spiele arbeiten mit einem Pegel von 50-100 ms. Viele Leute schreiben heute kritische Abschnitte in einer Sprache und den Rest eines Programms in einer anderen.
GlenPeterson
4
Wenn man bei diesem Test "25x mehr als C ++" betrachtet, muss man die ständige Hinzufügung der Laufzeit berücksichtigen (ungefähr 13 Mb). Je größer das Problem wird, desto geringer wird der Laufzeitspeicherbedarf als Prozentsatz des gesamten Programms. Wenn die C ++ - Speichernutzung weniger als 1 MB beträgt, erhalten Sie einen relativ konstanten Wert, wenn Sie die C ++ - Speichernutzung von der Java-Speichernutzung abziehen.

Antworten:

34

Die Speicherverwaltung ist äußerst relevant, da sie regelt, wie schnell etwas angezeigt wird, auch wenn das etwas viel Speicher hat. Das beste und kanonischste Beispiel sind AAA-Titel-Spiele wie Call of Duty oder Bioshock. Hierbei handelt es sich im Grunde genommen um Echtzeitanwendungen, die hinsichtlich Optimierung und Nutzung eine enorme Kontrolle erfordern. Es ist nicht die Verwendung an sich, die das Problem darstellt, sondern das Management.

Auf zwei Worte kommt es an: Garbage Collection. Garbage Collection-Algorithmen können zu leichten Performance-Einbußen führen oder sogar dazu, dass die Anwendung für ein oder zwei Sekunden hängen bleibt. Meist harmlos in einer Buchhaltungs-App, aber potenziell ruinös in Bezug auf die Benutzererfahrung in einem Call of Duty-Spiel. In Anwendungen, in denen es auf Zeit ankommt, können Sprachen, die überflüssig werden, sehr problematisch sein. Dies ist zum Beispiel eines der Designziele von Squirrel, das versucht, das Problem, das Lua mit seinem GC hat, zu beheben, indem stattdessen die Referenzzählung verwendet wird.

Ist es eher Kopfschmerzen? Sicher, aber wenn Sie eine präzise Steuerung benötigen, müssen Sie sich damit abfinden.

Weltingenieur
quelle
14
-1 "... im wahrsten Sinne des Wortes tödlich in einem Spiel ..." - Meine tägliche Arbeit ist ein sicherheitskritisches System wie die Sicherheit des Lebens. Das Schlimmste, was in Spielesoftware passiert, ist, dass der Autor pleite geht, weil er beschissen ist und niemand es kauft. Dies ist ein Unterschied, der nicht zu vernachlässigen ist.
Mattnz
4
@ Mattnz Schlechte Wortwahl meinerseits. Es wurde behoben. Es war nicht meine Absicht, irgendetwas zu trivialisieren.
Welt Ingenieur
19
@ Mattnz: Wenn Sie mit Spielen vertraut sind, bedeutet er offensichtlich, dass dies für Ihren Charakter tödlich sein könnte , was eine völlig wahre Aussage ist.
Mason Wheeler
8
+1, weil der Antwortende einen Diamanten hat, daher muss die Antwort richtig sein.
PSR
8
Abfallsammler in Echtzeit gibt es schon seit Ewigkeiten.
Jörg W Mittag
30

Der eigentliche Baustein war die Speicherzuweisung - im schlimmsten Fall hat Java satte 52-mal mehr Speicher als C und 25-mal mehr als C ++ zugewiesen.

Haben Sie verstehen die Zahlen Sie Ihre Frage auf der Basis?

  • Wie viel Speicher wurde zugewiesen?
  • Was machten die Programme?

Wenn es große Unterschiede zwischen diesen Java- und C-Programmen gibt, ist dies meist die Standard-JVM-Speicherzuordnung im Vergleich zu den Anforderungen von libc:

  • n-body
    Java-Programm 13.996 KB :: C-Programm 320 KB :: Free Pascal 8 KB

Sehen Sie sich die Aufgaben an, für die die Zuweisung von Speicher erforderlich ist (oder verwenden Sie zusätzliche Puffer, um Ergebnisse von Multicore-Programmen zu sammeln):

  • mandelbrot
    Java-Programm 67 , 880 KB :: C-Programm 30 , 444 KB

  • k-Nukleotid-
    Java-Programm 494 , 040 KB :: C-Programm 153 , 452 KB

  • Reverse-Complement-
    Java-Programm 511 , 484 KB :: C-Programm 248 , 632 KB

  • Regex-DNA-
    Java-Programm 557 , 080 KB :: C-Programm 289 , 088 KB


  • Java-Programm für Binärbäume 506 , 592 KB :: C-Programm 99 , 448 KB

... sollte die Speichernutzung heute ein Problem sein, wenn Sie eine Allzwecksprache auswählen?

Es hängt davon ab, ob die spezifische Verwendung für Ihren spezifischen Lösungsansatz für die spezifischen Probleme, die Sie lösen müssen, durch die spezifischen Grenzen des verfügbaren Speichers auf der spezifischen Plattform, die verwendet wird, eingeschränkt wird.

igouy
quelle
3
Ihr Argument über das Eingraben in die Zahlen ist gültig, und auf dieser Website gibt es mit Sicherheit einige Haftungsausschlüsse, die sich mit ihren Tests befassen. Ihre Antwort würde gestärkt, wenn Sie sich direkt mit der Kernfrage befassen: "Sollte die Speichernutzung ein Problem sein?"
1
Ausgezeichnete Antwort, die relativ schlechte Frage gerettet hat (vage spezifizierter Benchmark ist noch schlimmer als vorzeitige Optimierung :). Daten, die die Analyse unterstützen, sind gut präsentiert, konkret und bieten gute Denkanstöße. Auf jeden Fall eine "vorbildliche Antwort" Kopfgeld wert .
gnat
17

Wie bei allen Dingen ist es ein Kompromiss.

Wenn Sie eine Anwendung erstellen, die auf einem einzelnen Benutzer-Desktop ausgeführt werden soll und von der vernünftigerweise erwartet werden kann, dass sie einen großen Teil des Arbeitsspeichers auf diesem Computer steuert, lohnt es sich möglicherweise, die Speichernutzung für die Implementierungsgeschwindigkeit zu opfern. Wenn Sie auf denselben Computer abzielen, aber ein kleines Dienstprogramm erstellen, das mit einer Reihe anderer speicherhungriger Anwendungen konkurrieren wird, die gleichzeitig ausgeführt werden, sollten Sie bei diesem Kompromiss vorsichtiger vorgehen. Ein Benutzer kann mit einem Spiel gut zurechtkommen, das seinen gesamten Speicher benötigt, wenn es ausgeführt wird (obwohl World Engineer darauf hinweist, dass er Ich mache mir Sorgen, wenn der Müllsammler beschließt, die Aktion regelmäßig anzuhalten, um einen Sweep durchzuführen. Sie sind wahrscheinlich weniger begeistert, wenn der Musikplayer, den sie im Hintergrund laufen lassen, während sie andere Dinge tun, eine Tonne Speicher auffressen und stört ihre Arbeitsfähigkeit. Wenn Sie eine webbasierte Anwendung erstellen, wird durch den auf den Servern verwendeten Arbeitsspeicher die Skalierbarkeit eingeschränkt, sodass Sie mehr Geld für mehr Anwendungsserver ausgeben müssen, um dieselbe Benutzergruppe zu unterstützen. Dies kann erhebliche Auswirkungen auf die Wirtschaftlichkeit des Unternehmens haben. Sie sollten daher sehr vorsichtig sein, wenn Sie diesen Kompromiss eingehen. Jeder Speicher, den Sie auf den Servern verwenden, schränkt Ihre Skalierbarkeit ein und zwingt Sie dazu, mehr Geld für mehr Anwendungsserver auszugeben, um dieselbe Gruppe von Benutzern zu unterstützen. Dies kann erhebliche Auswirkungen auf die Wirtschaftlichkeit des Unternehmens haben. Sie sollten daher sehr vorsichtig sein, wenn Sie diesen Kompromiss eingehen. Jeder Speicher, den Sie auf den Servern verwenden, schränkt Ihre Skalierbarkeit ein und zwingt Sie dazu, mehr Geld für mehr Anwendungsserver auszugeben, um dieselbe Gruppe von Benutzern zu unterstützen. Dies kann erhebliche Auswirkungen auf die Wirtschaftlichkeit des Unternehmens haben. Sie sollten daher sehr vorsichtig sein, wenn Sie diesen Kompromiss eingehen.

Justin Cave
quelle
8

Dies hängt von einer Reihe von Faktoren ab, insbesondere von der Größe, in der Sie arbeiten.

Nehmen wir aus Gründen der Argumentation einen 30-fachen Unterschied im Arbeitsspeicher und einen 2-fachen Unterschied in der CPU-Auslastung an.

Wenn es sich um ein interaktives Programm handelt, das 10 Megabyte Arbeitsspeicher und 1 Millisekunde CPU benötigt, wenn es in C geschrieben wird, ist es ziemlich belanglos - 300 Megabyte Arbeitsspeicher und 2 Millisekunden sind auf einem typischen Desktop normalerweise völlig irrelevant. und es ist unwahrscheinlich, dass dies selbst auf einem Telefon oder Tablet viel bedeutet.

Der Unterschied zwischen etwa der Hälfte der Ressourcen eines Servers und der Notwendigkeit von 15 Servern ist jedoch ein viel größerer Schritt - zumal das Skalieren auf 15 Server wahrscheinlich viel zusätzlichen Aufwand erfordert, um sich zu entwickeln, anstatt weniger. Was die zukünftige Expansion betrifft, deuten dieselben Faktoren, die Sie erwähnen, darauf hin, dass Sie es sind, wenn Ihr Kundenstamm nicht massiv wächst und wenn er jetzt auf einem Server ausgeführt wird kann dies problemlos durch einen neueren Server ersetzen.

Der andere Faktor, den Sie wirklich berücksichtigen müssen, ist der genaue Unterschied in den Entwicklungskosten, den Sie für Ihre spezielle Aufgabe feststellen werden. Im Moment betrachten Sie im Grunde eine Seite einer Gleichung. Um eine gute Vorstellung von Kosten und Nutzen zu erhalten, müssen Sie (offensichtlich genug) sowohl Kosten als auch Nutzen betrachten, und nicht nur einen für sich. Die eigentliche Frage lautet im Grunde: "Ist x größer als y?" - aber Sie können das nicht feststellen, indem Sie nur x betrachten. Sie müssen sich natürlich auch y ansehen.

Jerry Sarg
quelle
2
+1 für das Notieren der Skala. Werfen Sie einen Blick auf diesen Artikel , um das Ressourcenmanagement im großen Maßstab wirklich zu würdigen.
Guy Coder
6

Speicherverwaltung ist in der heutigen Welt absolut relevant. Allerdings nicht so, wie Sie es vielleicht erwarten. Selbst in Sprachen, in denen Müll gesammelt wird, müssen Sie sicherstellen, dass Sie kein Referenzleck haben

Sie machen etwas falsch, wenn dies Ihr Code ist:

static List<string> Cache;

...
Cache.Add(foo); //and then never remove anything from Cache

Die Garbage Collection kann nicht auf magische Weise wissen, dass Sie nie wieder einen Verweis verwenden werden, es sei denn, Sie machen ihn so, dass Sie ihn nicht wieder verwenden können. Auf diese Weise warnen Cache=nullSie den Garbage Collector effektiv, dass "Hey, das werde ich nicht können greifen Sie nicht mehr darauf zu. Tun Sie, was Sie wollen. "

Es ist komplizierter als das, aber Referenzlecks sind genauso, wenn nicht sogar schädlicher als herkömmliche Speicherlecks.

Es gibt auch Orte, an denen Sie keinen Müllsammler unterbringen können. Beispielsweise ist der ATTiny84 ein Mikrocontroller mit 512 Byte Code-ROM und 32 Byte RAM. Viel Glück! Das ist ein Extrem und würde wahrscheinlich nur in Assembler programmiert werden, aber immer noch. In anderen Fällen verfügen Sie möglicherweise über 1 MB Arbeitsspeicher. Sicher, Sie könnten einen Garbage Collector einsetzen, aber wenn der Prozessor sehr langsam ist (entweder aufgrund von Einschränkungen oder um die Batterie zu schonen), sollten Sie keinen Garbage Collector verwenden, da es zu teuer ist, das zu verfolgen, was ein Programmierer wissen könnte .

Es wird auch erheblich schwieriger, die Garbage Collection zu verwenden, wenn Sie garantierte Antwortzeiten benötigen. Wenn Sie beispielsweise einen Herzmonitor oder Ähnliches haben und 1an einem Port einen empfangen , müssen Sie sicherstellen, dass Sie innerhalb von 10 ms mit einem geeigneten Signal oder Ähnlichem darauf reagieren können. Wenn der Garbage Collector mitten in Ihrer Antwortroutine einen Pass ausführen muss und es 100 ms dauert, bis er antwortet, ist möglicherweise jemand tot. Die Speicherbereinigung ist sehr schwierig, wenn nicht sogar unmöglich, wenn zeitliche Anforderungen garantiert werden müssen.

Selbstverständlich gibt es auch bei moderner Hardware Fälle, in denen Sie diese zusätzlichen 2% der Leistung benötigen, indem Sie sich nicht um den Overhead eines Garbage Collectors kümmern.

Earlz
quelle
3

Wie Donald Knuth sagte, ist vorzeitige Optimierung die Wurzel allen Übels. Machen Sie sich keine Sorgen, es sei denn, Sie haben Grund zu der Annahme, dass das Gedächtnis der Engpass sein wird. Und da Moores Gesetz immer noch eine erhöhte Speicherkapazität bietet (auch wenn wir keinen schnelleren Single-Thread-Code erhalten), gibt es allen Grund zu der Annahme, dass der Speicher in Zukunft noch weniger eingeschränkt sein wird als wir sind heute.

Das heißt, wenn Optimierung nicht verfrüht ist, tun Sie es auf jeden Fall. Ich persönlich arbeite gerade an einem Projekt, in dem ich meine Speichernutzung sehr genau verstehe. Ich brauche eine präzise Steuerung, und ein Mülleimer würde mich umbringen. Ich mache dieses Projekt daher in C ++. Aber diese Wahl scheint für mich alle paar Jahre ein Ereignis zu sein. (Hoffentlich werde ich in ein paar Wochen C ++ noch ein paar Jahre nicht mehr berühren.)

btilly
quelle
4
Diese Einstellung führt dazu, dass auf unglaublich langsamen Computern, auf denen ständig Paging ausgeführt wird, aufgeblähte Unternehmenssoftware auftritt. Jeder sagt: "Sicher, meine App nimmt mehr Speicherplatz in Anspruch, aber wen interessiert das, sie ist praktisch kostenlos!" und dann haben Sie einen ganzen Stapel speicherhungriger Apps, mit denen ein 4-GB-RAM-Rechner langsamer läuft als ein 512-MB-RAM-Rechner vor 10 Jahren.
MrFox
@MrFox Tatsächlich ist das Problem bei Unternehmenssoftware, dass die Leute, die sich dafür entscheiden, es zu verwenden, nicht die Leute sind, die darunter leiden. Unter lists.canonical.org/pipermail/kragen-tol/2005-April/000772.html finden Sie eine hervorragende Beschreibung der Fehlerursache . Haben Sie im Übrigen meinen Hinweis verpasst, dass es manchmal notwendig ist, sich Gedanken über die Speichernutzung zu machen?
Mittwoch,
3

Für Menschen, die mit "Big Data" zu tun haben, ist die Speicherverwaltung immer noch ein großes Problem. Programme in den Bereichen Astronomie, Physik, Bioinformatik, maschinelles Lernen usw. müssen sich alle mit Multi-Gigabyte-Datensätzen befassen, und die Programme werden viel schneller ausgeführt, wenn die relevanten Teile im Speicher gehalten werden können. Sogar das Ausführen auf einem Computer mit 128 GB RAM löst das Problem nicht.

Es gibt auch die Frage, wie Sie die GPU nutzen können, obwohl Sie dies vielleicht als eingebettetes System einstufen würden. Die meiste Mühe bei der Verwendung von CUDA oder OpenCL beruht auf Speicherverwaltungsproblemen beim Übertragen von Daten vom Hauptspeicher in den GPU-Speicher.

Charles E. Grant
quelle
1

Um ehrlich zu sein, eine Menge Java gibt sich einigen wirklich und sinnlos klassenexplosiven Mustern hin, die nur Leistung und Schweinegedächtnis ermorden, aber ich frage mich, wie viel von diesem Gedächtnis nur die JVM ist, die Sie theoretisch (heh) ausführen lassen gleiche App in mehreren Umgebungen, ohne dass neue vollständig neu geschrieben werden müssen. Aus diesem Grund dreht sich alles um die Frage nach dem Design: "Wie viel Speicherplatz Ihres Benutzers ist Ihnen ein solcher Entwicklungsvorteil wert?"

Dies ist meiner Meinung nach ein absolut lohnender und vernünftiger Kompromiss. Was mich jedoch aufregt, ist die Vorstellung, dass wir, weil moderne PCs so leistungsfähig und der Speicher so billig ist, solche Bedenken und aufgedunsenen Funktionen und den aufgedunsenen Code völlig ignorieren und bei der Auswahl so faul sein können, dass es so aussieht, als ob es eine Menge Zeug wäre Das mache ich jetzt auf einem Windows-PC, dauert genauso lange wie in Windows '95. Im Ernst, Word? Wie viel neuen Mist, den 80% ihrer Benutzer tatsächlich brauchen, hätten sie möglicherweise in 18 Jahren hinzufügen können? Ziemlich sicher, dass wir Rechtschreibprüfung vor Windows hatten, oder? Aber wir sprachen über Erinnerungen, die nicht unbedingt schnell sind, wenn Sie genug davon haben, also schweife ich ab.

Aber wenn Sie die App in 2 Wochen fertig stellen können, um vielleicht ein paar Megabyte mehr als 2 Jahre, um die Version nur für wenige K zu erhalten, ist es natürlich eine Überlegung wert, wie viele Megabytes im Vergleich zu ( Ich vermute) 4-12 Gigs auf dem Computer eines durchschnittlichen Benutzers, bevor ich mich über die Idee lustig mache, so schlampig zu sein.

Aber was hat das mit Scala jenseits der Kompromissfrage zu tun? Nur weil es sich um eine Garbage Collection handelt, heißt das nicht, dass Sie nicht immer versuchen sollten, über den Datenfluss nachzudenken, was sich in Bereichen und Verschlüssen befindet, und ob die Daten herumstehen oder so verwendet werden sollten, wie es sein wird von GC freigegeben, wenn es nicht mehr benötigt wird. Das ist etwas, worüber auch wir JavaScript-Benutzeroberflächen-Entwickler nachdenken mussten und das wir hoffentlich weiter machen werden, wenn wir uns auf andere Problembereiche wie den perfiden Krebs ausbreiten (den Sie alle mit Flash oder Applets hätten töten sollen oder etwas, wenn Sie die Chance dazu hatten). das sind wir.

Erik Reppen
quelle
0

Wird die Speicherverwaltung beim Programmieren zu einem irrelevanten Problem?

Speicherverwaltung (oder -steuerung) ist eigentlich der Hauptgrund, warum ich C und C ++ verwende.

Speicher ist jetzt vergleichsweise billig.

Nicht schnelles Gedächtnis. Wir sehen uns noch eine kleine Anzahl von Registern an, etwa 32 KB Datencache für L1 auf i7, 256 KB für L2 und 2 MB für L3 / Core. Das gesagt:

Wenn wir nicht in Bezug auf Zielplattformen mit strengen Einschränkungen des Arbeitsspeichers (dh eingebettete Systeme und dergleichen) sprechen, sollte die Speichernutzung heutzutage ein Problem bei der Auswahl einer Allzwecksprache sein?

Speicherauslastung auf einer allgemeinen Ebene, vielleicht nicht. Ein bisschen unpraktisch finde ich, dass ich die Idee eines Notizblocks nicht mag, der beispielsweise 50 Megabyte DRAM und Hunderte Megabyte Festplattenspeicher beansprucht, obwohl ich das zu wenig und reichlich mehr habe. Ich bin schon lange dabei und es fühlt sich für mich einfach komisch und unangenehm an, zu sehen, wie eine so einfache Anwendung relativ viel Speicherplatz für das benötigt, was mit Kilobyte machbar sein sollte. Das heißt, ich könnte vielleicht mit mir selbst leben, wenn mir so etwas begegnet wäre, wenn es immer noch nett und ansprechbar wäre.

Der Grund, warum mir die Speicherverwaltung in meinem Bereich wichtig ist, besteht darin, die Speichernutzung im Allgemeinen nicht so stark zu reduzieren. Hunderte von Megabyte Arbeitsspeicher belasten eine Anwendung nicht unbedingt auf nicht triviale Weise, wenn nicht häufig auf diesen Arbeitsspeicher zugegriffen wird (z. B. nur durch Klicken auf eine Schaltfläche oder eine andere Form der Benutzereingabe, die nur in Ausnahmefällen erfolgt) Es geht um koreanische Starcraft-Spieler, die möglicherweise millionenfach pro Sekunde auf eine Schaltfläche klicken.

Der Grund, warum es in meinem Bereich wichtig ist, dass der Speicher eng und dicht beieinander ist, auf den in diesen kritischen Pfaden sehr häufig zugegriffen wird (z. B. über jeden einzelnen Frame geschleift zu werden). Wir möchten nicht jedes Mal einen Cache-Fehler haben, wenn wir auf eines von Millionen Elementen zugreifen, auf die alle in einer Schleife bei jedem einzelnen Frame zugegriffen werden müssen. Wenn wir den Speicher in großen Blöcken von langsamem auf schnelles Speichern in der Hierarchie verschieben, z. B. 64-Byte-Cache-Zeilen, ist es sehr hilfreich, wenn diese 64-Byte-Blöcke alle relevanten Daten enthalten, wenn wir mehrere Datenelemente in diese 64-Byte-Blöcke einfügen können und wenn unsere Zugriffsmuster so sind, dass wir sie alle verwenden, bevor die Daten gelöscht werden.

Die Daten, auf die häufig zugegriffen wird, für die Millionen Elemente umfassen möglicherweise nur 20 Megabyte, obwohl wir Gigabyte haben. Es macht immer noch einen großen Unterschied, wie viele Frameraten diese Daten bei jedem einzelnen Frame durchlaufen, wenn der Speicher knapp und dicht beieinander ist, um Cache-Ausfälle zu minimieren. Hier ist die Speicherverwaltung / -steuerung von großem Nutzen. Einfaches visuelles Beispiel für eine Kugel mit einigen Millionen Eckpunkten:

Bildbeschreibung hier eingeben

Das obige ist tatsächlich langsamer als meine veränderbare Version, da es eine beständige Datenstrukturdarstellung eines Netzes testet, aber abgesehen davon hatte ich Mühe, solche Bildraten auch bei der Hälfte dieser Daten zu erreichen (zugegebenermaßen ist die Hardware seit meinen Kämpfen schneller geworden ), weil ich es nicht geschafft habe, Cache-Ausfälle und den Speicherbedarf für Mesh-Daten zu minimieren. Netze sind einige der schwierigsten Datenstrukturen, mit denen ich mich in diesem Zusammenhang befasst habe, weil sie so viele voneinander abhängige Daten speichern, die synchron bleiben müssen, wie Polygone, Kanten, Scheitelpunkte, so viele Texturabbildungen, wie der Benutzer anfügen möchte, Knochengewichte, Farbkarten, Auswahlsets, Morph-Ziele, Kantengewichte, Polygonmaterialien usw. usw. usw.

Ich habe in den letzten Jahrzehnten eine Reihe von Mesh-Systemen entworfen und implementiert, deren Geschwindigkeit oft sehr proportional zur Speichernutzung war. Obwohl ich mit so viel mehr Speicher arbeite als zu Beginn, sind meine neuen Mesh-Systeme über 10-mal schneller als mein erstes Design (vor fast 20 Jahren) und zu einem großen Teil, weil sie ungefähr 1/10 davon verbrauchen die Erinnerung. Die neueste Version verwendet sogar eine indizierte Komprimierung, um so viele Daten wie möglich zu komprimieren, und trotz des Verarbeitungsaufwands der Dekomprimierung hat die Komprimierung tatsächlich die Leistung verbessert, da wir wiederum so wenig wertvollen schnellen Speicher haben. Ich kann jetzt eine Million Polygonnetze mit Texturkoordinaten, Kantenfalten, Materialzuordnungen usw. zusammen mit einem räumlichen Index in etwa 30 Megabyte anpassen.

Hier ist der veränderbare Prototyp mit über 8 Millionen Vierecken und einem Unterteilungsschema für mehrere Reifen auf einem i3 mit einem GF 8400 (dies war vor einigen Jahren). Es ist schneller als meine unveränderliche Version, wird aber nicht in der Produktion verwendet, da ich die unveränderliche Version für viel einfacher zu warten und die Leistung nicht allzu schlecht finde. Beachten Sie, dass das Drahtgitter keine Facetten, sondern Flecken anzeigt (die Drähte sind tatsächlich Kurven, da sonst das gesamte Netz durchgehend schwarz ist), obwohl alle Punkte in einer Facette vom Pinsel geändert werden.

Bildbeschreibung hier eingeben

Auf jeden Fall wollte ich oben nur einiges davon zeigen, um einige konkrete Beispiele und Bereiche zu zeigen, in denen die Speicherverwaltung so hilfreich und hoffentlich auch so ist, dass die Leute nicht glauben, ich spreche nur aus meinem Hintern. Ich neige dazu, ein bisschen irritiert zu werden, wenn Leute sagen, Speicher sei so reichlich vorhanden und billig, weil es sich um langsamen Speicher wie DRAM und Festplatten handelt. Es ist immer noch so klein und wertvoll, wenn es um schnelles Gedächtnis geht, und die Leistung bei wirklich kritischen (dh nicht für alle Fälle üblichen) Pfaden bezieht sich darauf, auf diese kleine Menge an schnellem Gedächtnis zu spielen und es so effektiv wie möglich zu nutzen .

Für diese Art von Dingen ist es sehr hilfreich, mit einer Sprache zu arbeiten, mit der Sie übergeordnete Objekte wie beispielsweise C ++ entwerfen und diese Objekte dennoch in einem oder mehreren zusammenhängenden Arrays speichern können, wobei der Speicher von garantiert wird Alle diese Objekte werden zusammenhängend und ohne unnötigen Speicheraufwand pro Objekt dargestellt (Beispiel: Nicht alle Objekte benötigen Reflektion oder virtuellen Versand). Wenn Sie diese leistungskritischen Bereiche tatsächlich betreten, wird es tatsächlich zu einem Produktivitätsschub, wenn Sie die Speicherkontrolle beispielsweise über das Fummeln mit Objektpools und die Verwendung primitiver Datentypen ausüben, um Objekt-Overhead und GC-Kosten zu vermeiden und den Zugriff auf Speicher häufig zu halten zusammen zusammenhängend.

Daher ist Speicherverwaltung / -kontrolle (oder deren Fehlen) in meinem Fall tatsächlich ein dominierender Grund für die Wahl der Sprache, mit der ich Probleme am produktivsten angehen kann. Ich schreibe definitiv meinen Anteil an Code, der nicht leistungskritisch ist, und ich neige dazu, Lua zu verwenden, das von C aus ziemlich einfach einzubetten ist.


quelle