[英]Why is using a Tuple faster than a List in this example?
我寫了一個C#類,用一些數據填充“雙打列表列表”(無論數據是什么,現在它可能只是一些垃圾:)),用於測試目的:
這是代碼:
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;
}
我將此代碼的執行速度與以下內容進行了比較:(用元組替換double的列表)
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;
}
事實證明,使用元組似乎要快得多。 我為不同的List大小運行了這段代碼(從200,000個元素 - 列表中的> 5百萬個元素),這是我得到的結果:
我無法真正理解這一點。 為什么我會有如此顯着的差異? 使用存儲相同類型對象的元組(這里加倍)並沒有多大意義。 我寧願使用List /數組來做到這一點:我做錯了什么? 是否有一種方法可以使案例#1以比案例#2更快/更快的速度運行?
謝謝!
new Tuple<double, double, double>(i, 10 * i, 100 * i)
和new List<double>(3) { i, 10*i, 100*i}
之間存在差異。
第一個是超級簡單 - 只有3個任務:
public Tuple(T1 item1, T2 item2, T3 item3) {
m_Item1 = item1;
m_Item2 = item2;
m_Item3 = item3;
}
第二個實際上是由編譯器轉換為3個Add
方法調用:
var temp = new List<double>(3);
temp.Add(i);
temp.Add(10 * i);
temp.Add(100 * i);
Add
不僅僅是一項任務:
public void Add(T item) {
if (_size == _items.Length) EnsureCapacity(_size + 1);
_items[_size++] = item;
_version++;
}
運行更多代碼,執行速度更慢。 非常簡單..
正如在@ Marcin的回答中提到的那樣,即使初始化List<T>
初始化列表IL仍然在內部具有Add()
函數,即使您在構造期間最初指定列表的容量也是如此。 就像你在你的例子中所做的那樣
是否有一種方法可以使案例#1以比案例#2更快/更快的速度運行?
可能的解決方案可能是直接分配給成員:
list[0] =
list[1] =
list[2] =
在這種情況下,IL看起來像這樣:
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
更快,因為它是一個簡單的賦值。
或者,使用簡單的數組 。 表現應該更好。 不過,有了這樣的東西,比如A vs B速度,只有經過具體測量才能得到真正的答案。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.