2015-01-28 30 views
14

Visual Studio 2013 performans sihirbazla kodumun .NET bellek ayırma çözümlenirken, bir çok bayt ayırma belirli bir işlev olduğunu fark ettim (büyük bir döngüde çağrıldığı için). Ancak profilleme raporunda vurgulanan işleve bakmak, neden hiç bellek ayırdığını anlamadım.nonquting linq neden bellek ayırma C#

Neyin yaşandığını daha iyi anlamak için, tahsisatlara neden olan kodu izole ettim. Bu, aşağıdaki LinqAllocationTester sınıfına benzerdi. Test kod yolunda hiçbir zaman çalıştırılmamış olan bu işlevdeki LINQ kodunu bir kez daha açıkladım, artık bir bellek ayrılmadı. NonLinqAllocationTester sınıfı bu davranışı taklit eder. LINQ kodunu normal bir döngü ile değiştirmek, ayrıca bellek ayırmalarına izin vermez.

.NET bellek ayırma sınamasını aşağıdaki sınama kodunda çalıştırırsam, LinqAllocationTester'ın 100.000 ayırmaya (çağrı başına 1) neden olduğunu gösterirken NonLinqAllocationTester öğesinin hiçbiri yoktur. UseLinq öğesinin her zaman false olduğunu unutmayın, bu nedenle LINQ kodunun kendisi gerçekte yürütülmez.

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 

Peki neden yapar LINQ kod neden bellek ayırmalarını infaz non? LINQ fonksiyonlarından kaçınmanın yanı sıra bunu engellemenin bir yolu var mı?

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; 
     } 
    } 
} 

cevap

7

Sen LINQ ifadesi için DisplayClass ilk if-şube dışında yöntemin başında başlatıldı olacağını görmek için üretilen IL bir göz alabilir. Bunun nedeni, yöntemin başlangıcında lambda ifadesi için kapamanın üretilmesidir (ilk değerin göründüğü yer).

IL:

if (useLinq) 
{ 
    int value2 = value; 
    return values.Max(x => Math.Abs(value2 - x)); 
} 

ekstra ayırmalar artık olmamalı: Eğer böyle bir dar kapsamlı değişkene değerinizi kopyalarsanız

IL_0000: ldnull 
IL_0001: stloc.2 
IL_0002: newobj instance void ConsoleApplication2.LinqAllocationTester/'<>c__DisplayClass2'::.ctor() 
IL_0007: stloc.3 
IL_0008: ldloc.3 
IL_0009: ldarg.1 
IL_000a: stfld int32 ConsoleApplication2.LinqAllocationTester/'<>c__DisplayClass2'::'value' 
IL_000f: nop 
IL_0010: ldarg.0 
IL_0011: ldfld bool ConsoleApplication2.LinqAllocationTester::useLinq 
IL_0016: ldc.i4.0 
IL_0017: ceq 
IL_0019: stloc.s CS$4$0001 
IL_001b: ldloc.s CS$4$0001 
IL_001d: brtrue.s IL_0042 

.

İlgili konular