|
|
|
|
|
本文將通過示例,對比有無指定List
集合??容量的情況下,其程序運行速度的快慢,這是一個有意思的測試。
代碼如下:
[Benchmark]
public void NonFixedCapacityTest()
{
var items = new List<decimal>();
for (int i = 0; i < 1000000; i++)
{
items.Add(i);
}
}
[Benchmark]
public void FixedCapacityTest()
{
const int capacity = 1000000;
var items = new List<decimal>(capacity);
for (int i = 0; i < capacity; i++)
{
items.Add(i);
}
}
這兩種方法完成相同的任務——使用foreach
循環(huán)填充整數(shù)集合。唯一的區(qū)別是在FixedCapacityTest
方法中構造函數(shù)被初始化為某個數(shù)字。這個簡單的技巧使其運行速度是NonFixedCapacityTest
的2倍。
因為它的List<T>
的實現(xiàn)方式是將元素存儲在數(shù)組中,數(shù)組是固定大小的數(shù)據(jù)結構。當開發(fā)人員List<T>
在未指定其容量的情況下進行實例化時,將分配一個默認容量數(shù)組。當數(shù)組已滿時,將分配一個新的更大的數(shù)組,并將舊數(shù)組中的值復制到新數(shù)組中。
提前指定容量可以消除分配、復制和舊數(shù)組垃圾回收的開銷。指定集合的??容量應該是開發(fā)人員的默認選擇,如果他們事先知道有多少項目將被添加到集合中。
容量設置不僅適用于 List
集合,還適用于其他集合,例如Dictionary<TKey, TValue>, HashSet<T>等等。
有時結構(struct)比類(class)速度快得多
開發(fā)人員通??赡苄枰峙湟粋€數(shù)組或List<T>
在內存中存儲數(shù)萬個對象。這個任務可以使用類或結構來解決。
public class PointClass
{
public int X { get; set; }
public int Y { get; set; }
}
public struct PointStruct
{
public int X { get; set; }
public int Y { get; set; }
}
[Benchmark]
public void ListOfObjectsTest()
{
const int length = 1000000;
var items = new List<PointClass>(length);
for (int i = 0; i < length; i++)
{
items.Add(new PointClass() { X = i, Y = i });
}
}
[Benchmark]
public void ListOfStructsTest()
{
const int length = 1000000;
var items = new List<PointStruct>(length);
for (int i = 0; i < length; i++)
{
items.Add(new PointStruct() { X = i, Y = i});
}
}
可以看到, ListOfObjectTest
和ListOfStructsTest
之間的唯一區(qū)別是第一個測試創(chuàng)建類的實例PointClass
,而第二個測試創(chuàng)建結構的實例PointStruct
。運行結果是使用結構的代碼比使用類的代碼運行速度快 15 倍。
存在如此大的時間差異是因為在類的情況下,CLR 必須將一百萬個對象分配到托管堆并將它們的引用存儲回集合List<T>
。在結構的情況下,將有唯一的對象分配到托管堆中,它是集合List<T>
的實例 ,一百萬個結構將嵌入到該單個集合實例中。
相關文章