Während ich die .NET-Speicherzuweisung meines Codes mit dem Visual Studio 2013-Leistungsassistenten analysierte, bemerkte ich eine bestimmte Funktion, die viele Bytes zuweist (da sie in einer großen Schleife aufgerufen wird). Aber wenn ich mir die Funktion ansehe, die im Profiling-Bericht hervorgehoben ist, habe ich nicht verstanden, warum überhaupt Speicher zugewiesen wurde.nicht ausführende linq verursacht Speicherzuweisung C#
Um besser zu verstehen, was passiert ist, isolierte ich den Code, der die Zuweisungen verursachte. Dies war ähnlich der LinqAllocationTester Klasse unten.
Sobald ich den LINQ-Code in dieser Funktion auskommentiert habe, die im getesteten Codepfad sowieso nie ausgeführt wurde, wurde kein Speicher mehr zugewiesen. Die NonLinqAllocationTester-Klasse imitiert dieses Verhalten. Das Ersetzen des LINQ-Codes durch eine normale Schleife lässt auch keine Speicherzuweisungen zu.
Wenn ich den .NET-Speicherzuweisungstest für den Testcode unten ausführen, zeigt es, dass der LinqAllocationTester 100.000 Zuordnungen (1 pro Aufruf) verursacht, während der NonLinqAllocationTester keine hat. Beachten Sie, dass useLinq immer falsch ist, so dass der LINQ-Code selbst nie ausgeführt wird.
Function Name | Inclusive | Exclusive | Inclusive | Exclusive
| Allocations | Allocations | Bytes | Bytes
-------------------------------------------------------------------------------------
LinqAllocationTester.Test(int32) | 100.000 | 100.000 | 1.200.000 | 1.200.000
Program.Main(string[]) | 100.000 | 0 | 1.200.000 | 0
Warum funktioniert das nicht ausführen LINQ Code Ursache Speicherzuordnungen? Und gibt es eine Möglichkeit dies zu verhindern, neben der Vermeidung von LINQ-Funktionen?
class Program {
static void Main(string[] args) {
List<int> values = new List<int>() { 1, 2, 3, 4 };
LinqAllocationTester linqTester = new LinqAllocationTester(false, values);
NonLinqAllocationTester nonLinqTester = new NonLinqAllocationTester(false, values);
for (int i = 0; i < 100000; i++) {
linqTester.MaxDifference(i);
}
for (int i = 0; i < 100000; i++) {
nonLinqTester.MaxDifference(i);
}
}
}
internal class LinqAllocationTester {
private bool useLinq;
private List<int> values;
public LinqAllocationTester(bool useLinq, List<int> values) {
this.useLinq = useLinq;
this.values = values;
}
public int MaxDifference(int value) {
if (useLinq) {
return values.Max(x => Math.Abs(value - x));
} else {
int maxDifference = int.MinValue;
foreach (int value2 in values) {
maxDifference = Math.Max(maxDifference, Math.Abs(value - value2));
}
return maxDifference;
}
}
}
internal class NonLinqAllocationTester {
private bool useLinq;
private List<int> values;
public NonLinqAllocationTester(bool useLinq, List<int> values) {
this.useLinq = useLinq;
this.values = values;
}
public int MaxDifference(int value) {
if (useLinq) {
return 0;
} else {
int maxDifference = int.MinValue;
foreach (int value2 in values) {
maxDifference = Math.Max(maxDifference, Math.Abs(value - value2));
}
return maxDifference;
}
}
}