2016-07-20 36 views
6

Test amacıyla, bazı verilerle (verilerin ne olduğu önemli değil, şimdilik yalnızca birkaç çöp olabilir) bir "çiftler listesi listesi" ni doldurmaya çalışan bir C# sınıfı yazdım:Bu örnekte neden bir Listeden daha hızlı bir Tuple kullanıyorsunuz?

İşte

kodu: (a tuple tarafından çifte Listesi değiştirilmesi)

class test 
    { 
    public test() 
    { 
     _myListOfTuple = new List<Tuple<double, double, double>>(1000000); 
    } 
    public void Run() 
    { 
     for (int i = 0; i < _myListOfTuple.Capacity; i++) 
     { 
      _myListOfTuple.Add(
       new Tuple<double, double, double>(i, 10 * i, 100 * i) 
       ); //Populate the list with data 
     } 
    } 

    private List<Tuple<double, double, double>> _myListOfTuple; 
} 

tuple kullanarak görünüyor çıkıyor: aşağıdaki ile bu kodun yürütme hızını karşılaştırıldığında

class test 
    { 
    public test() 
    { 
     _myListOfList = new List<List<double>>(1000000); 
    } 
    public void Run() 
    { 
     for (int i = 0; i < _myListOfList.Capacity; i++) 
     { 
      _myListOfList.Add(
       new List<double>(3) { i, 10*i, 100*i} 
       ); //Populate the list with data 
     } 
    } 

    private List<List<double>> _myListOfList; 
} 

Oldukça hızlı olmak. Gerçekten bu bir kafamı alamayan

graph

: Ben olsun sonuçlarıdır burada ve - I (listede> 5 milyon elemanları 200.000 elementlerden) farklı Liste boyutları için kod parçasını koştu. Nasıl bu kadar önemli bir fark aldım? Aynı türdeki nesneleri depolayan bir Tuple'ın kullanılması (burada iki katına çıkar) çok anlamlı değildir. Bunu yapmak için bir Liste/dizi kullanmayı tercih ederim: ne yapıyorum yanlış? # 1 numaralı davadan # 1 hızlı/hızlı çalışmasını sağlayabilmem için bir yol var mı?

Teşekkürler!

+2

Bu neden bu kadar şaşırtıcı? Tam olarak 3 nesneyi depolamaktan daha fazla sayıda nesneyi saklamakla uğraşmak çok daha fazla iş gerektirir. – Servy

+0

Genel giderler. Bir şey için, bir çift kişilik bir tuple bir liste ile karşılaştırıldığında ne kadar yer beklerdiniz? Her tür için hangi alanların dahili olarak sahip olmasını bekliyorsunuz? –

+1

bile küçük farkları bile ölçeklendirmek onları büyük görünmesini sağlar .. – TaW

cevap

7

new Tuple<double, double, double>(i, 10 * i, 100 * i) ve new List<double>(3) { i, 10*i, 100*i} arasında bir fark vardır.

birincisi süper basittir - sadece 3 atamaları:

public Tuple(T1 item1, T2 item2, T3 item3) { 
    m_Item1 = item1; 
    m_Item2 = item2; 
    m_Item3 = item3; 
} 

aslında 3 Add yöntem haline derleyici tarafından dönüşür İkincisi çağırır:

var temp = new List<double>(3); 
temp.Add(i); 
temp.Add(10 * i); 
temp.Add(100 * i); 

Add sadece çok daha fazlasıdır atama:

public void Add(T item) { 
    if (_size == _items.Length) EnsureCapacity(_size + 1); 
    _items[_size++] = item; 
    _version++; 
} 

Daha fazla kod t koş, yavaş yürütme. Oldukça basit ..

başlangıçta belirtmek bile o, inşaat sırasında, hatta başlatıcı listesi IL tarafından List<T> başlatılıyor hala içinde Add() işlevi vardır ki listenin Capacity doğrudur @ içinde Marcin yanıtını belirtildiği gibi
+0

Cevabınız için bir demet teşekkürler .. bu çok mantıklı! @Tigran'ın önerdiği gibi, Listeyi bir dizi ile değiştirdim (yeni int [3] {i, 10 * i, 100 * i}) ve hız açısından çok benzer sonuçlar alıyorum :) – harveyAJ

2

. Senin örneğinde olduğu gibi.

# 1 numaralı davadan # 1 hızlı/hızlı çalışmasını sağlayabilmem için bir yol var mı?

olası çözüm üyelerine doğrudan atama olabilir: IL şuna benzer

list[0] = 
list[1] = 
list[2] = 

Bu durumda: basit bir görev olarak

IL_0000: ldc.i4.3  
IL_0001: newobj  System.Collections.Generic.List<System.Double>..ctor 
IL_0006: stloc.0  // list 
IL_0007: ldloc.0  // list 
IL_0008: ldc.i4.0  
IL_0009: ldc.r8  00 00 00 00 00 00 F0 3F 
IL_0012: callvirt System.Collections.Generic.List<System.Double>.set_Item 
IL_0017: ldloc.0  // list 
IL_0018: ldc.i4.1  
IL_0019: ldc.r8  00 00 00 00 00 00 24 40 
IL_0022: callvirt System.Collections.Generic.List<System.Double>.set_Item 
IL_0027: ldloc.0  // list 
IL_0028: ldc.i4.2  
IL_0029: ldc.r8  00 00 00 00 00 00 59 40 
IL_0032: callvirt System.Collections.Generic.List<System.Double>.set_Item 
IL_0037: ret 

set_Item hızlıdır. Veya Array numaralı telefonu kullanın. Performans daha iyi olmalıdır. Yine de, A vs B hızı gibi, bu tür şeylerle, gerçek cevap sadece somut ölçümden sonra olur.

İlgili konular