Jede iteration jedes "foreach" - Schleife generiert, die 24 Bytes der garbage-Speicher?
Mein Freund arbeitet mit Unity3D in C#. Und er sagte mir ausdrücklich:
Jeder iteration jeder "foreach" - Schleife generiert, die 24 Bytes der Müll
Speicher.
Und ich sehe auch, dass diese Informationen hier
Aber ist das wahr?
Den Absatz am meisten relevant zu meiner Frage:
Ersetzen Sie die "foreach" - Schleifen mit einfachen "for" - Schleifen. Für einige Grund,
jede iteration jedes "foreach" - Schleife generiert, die 24 Bytes der Müll
Speicher. Eine einfache Schleife 10 mal Durchlaufen gelassen 240 Byte Speicher
bereit, abgeholt zu werden, das war einfach inakzeptabel
- Das ist viel zu allgemein sind, eine Aussage zu ernst genommen werden. Verschiedene Sammlungen Verhalten sich verschiedene Möglichkeiten, mit
foreach
- der Autor ist nicht angegeben, was er redet. (Insbesondere mit arrays den compiler effektiv etwas erzeugen, entspricht derfor
Schleife sowieso.) - Ja, ich denken Sie das gleiche. Ende der 'foreach' langsamer 'für'?
- Es hängt ganz von dem jeweiligen Szenario ab. Jede Verallgemeinerung auf, die front ist wahrscheinlich falsch in einigen situation.
- Das ganze Artikel zu Lesen ist, als "Dies war für uns in unserer besonderen situation". Es möglicherweise oder möglicherweise nicht das gleiche für Sie.
- Tatsächlich, ich habe zu nehmen, dass Artikel mit einer Prise Salz, weil es behauptet ", den Aufruf der tag-Eigenschaft auf ein Objekt allokiert und kopiert die zusätzlichen Speicher" - wo
tag
hier ist einstring
- sorry, aber das ist einfach nicht wahr - alles, was geschieht, ist, dass der Verweis auf die vorhandene string-Objekt kopiert wird, die auf dem stack - es gibt kein extra Objekt Reservierung hier.
Du musst angemeldet sein, um einen Kommentar abzugeben.
foreach
ist ein Interessantes Biest; eine Menge Leute denken fälschlicherweise, es wird gebunden zuIEnumerable[<T>]
/IEnumerator[<T>]
, aber das ist einfach nicht der Fall. Als solche, es ist sinnlos zu sagen:Insbesondere hängt es davon ab, genau das, was Sie Durchlaufen. Zum Beispiel, eine Menge der Typen haben benutzerdefinierte Iteratoren -
List<T>
zum Beispiel - hat einestruct
-basierte iterator. Die folgenden weist null-Objekte:Jedoch ist es mit diesem Objekt-Zuweisungen:
Die sieht identisch, aber nicht durch ändern der
foreach
DurchlaufenIList<SomeType>
(die nicht über eine benutzerdefinierteGetEnumerator()
Methode, aber die setztIEnumerable<SomeType>
) wir zwingen es zu verwenden, dieIEnumerable[<T>]
/IEnumerator<T>
- API, die viel von der Notwendigkeit beinhalten ein Objekt.Bearbeiten VORBEHALT: Hinweis: ich gehe davon aus, dass hier die Einheit bewahren können, den Wert-Typ-Semantik der benutzerdefinierten iterator; wenn die Einheit gezwungen ist, sich zu erheben Strukturen auf Objekte, dann ehrlich gesagt sind alle Wetten ab.
Als es passiert ist, würde ich gerne sagen, "sicher, verwenden Sie
for
und einen indexer, in diesem Fall", wenn jede Zuordnung Fragen, aber grundsätzlich: eine Pauschale Aussage überforeach
ist wenig hilfreich und irreführend.GetEnumerator()
nennen, aber dieDispose()
. Sehen.foreach
Schleife, die ich beobachtet habe, schafft 24 bytes Müll gesammelt werden.Dein Freund der richtige ist, der folgende code erzeugt 24k von Müll, die jeden Rahmen in der Einheit von version 4.3.4:
Dieser zeigt die Zuordnung in der Unity profiler:
Laut folgendem link ist es ein bug in der version von mono verwendet wird, indem die Einheit, die Kräfte der struct-enumerator zu bekommen, boxed, das scheint wie eine vernünftige Erklärung, obwohl ich noch nicht verifiziert durch code-Inspektion: Blog-post diskutiert die Boxen-bug
Gibt es einige gute Ratschläge hier, foreach, aber ich muss Glockenspiel über der Marke s Kommentar oben über tags (leider habe ich nicht genug rep Kommentar unter seinem Kommentar), wo er erklärte,
Tatsächlich, den Aufruf der tag-Eigenschaft ist Müll. Meine Vermutung ist, dass intern die tag ' s werden gespeichert als ganze zahlen (oder eine andere einfache Art), und wenn die tag-Eigenschaft aufgerufen wird, die Einheit wandelt den int in einen string in eine interne Tabelle stellen.
Es trotzt Grund, denn die tag-Eigenschaft, die könnten genauso gut den string aus, dass die interne Tabelle, anstatt eine neue Zeichenfolge, aber aus welchem Grund auch immer, dies ist, wie es funktioniert.
Testen Sie dies selbst anhand der folgenden einfachen Komponente:
Wenn gameObject.- tag wurde nicht produziert Müll, dann die Erhöhung/Verringerung der Anzahl der Iterationen würde keinen Einfluss auf die GC-Zuteilung (in der Unity Profiler). In der Tat, wir sehen einen linearen Anstieg der GC-Verteilung wie die Anzahl der Iterationen erhöht.
Es ist auch erwähnenswert, dass die name-Eigenschaft verhält sich in genau der gleichen Art und Weise (wieder, der Grund, warum entzieht sich mir).