使用C#時,我注意到使用動態生成類型的實例與簡單結構填充列表時的性能差異。下面的代碼包含4種用於使用100,000個對象填充列表的不同方法。動態創建類型的性能
每種方法進行不同的:
Button1的:15毫秒
將Button2:31毫秒
將Button3 & 4:300毫秒
注意,對於按鈕3的代碼& 4從來到this topic
任何人都可以解釋爲什麼動態創建的對象更慢?
public struct DataRow
{
public double t;
public double vf;
public double im;
public double T { get { return t; } set { t = value; } }
public double Vf { get { return vf; } set { vf = value; } }
public double Im { get { return im; } set { im = value; } }
}
//Use struct defined above
private void button1_Click(object sender, EventArgs e)
{
int n = 0;
//adding rows
List<DataRow> myTable = new List<DataRow>();
DataRow myRow = new DataRow();
start = DateTime.Now;
while (n < 100000)
{
myRow.T = n * 1.0;
myRow.Vf = 2.0;
myRow.Im = 4.0;
myTable.Add(myRow);
n++;
}
end = DateTime.Now;
System.TimeSpan diff = end.Subtract(start);
label2.Text = diff.Seconds.ToString();
label4.Text = diff.Milliseconds.ToString();
dataGridView1.DataSource = myTable;
}
//define the list as it is done on buttons 3 & 4 but use the static struct
private void button2_Click(object sender, EventArgs e)
{
Type myType = typeof(DataRow);
Type listType = typeof(List<>);
Type myListType = listType.MakeGenericType(myType);
IList myTable = (IList)Activator.CreateInstance(myListType);
DataRow bRow = new DataRow();
int n = 0;
start = DateTime.Now;
while (n < 100000)
{
bRow.t = n * 1.0;
bRow.vf = 2.0;
bRow.im = 4.0;
myTable.Add(bRow);
n++;
}
end = DateTime.Now;
System.TimeSpan diff = end.Subtract(start);
label2.Text = diff.Seconds.ToString();
label4.Text = diff.Milliseconds.ToString();
dataGridView1.DataSource = myTable;
}
//Create assy at runtime and load dll
private void button3_Click(object sender, EventArgs e)
{
Type myType = CreateDynRow();
Assembly myAssy = Assembly.LoadFrom("DynaRowAssy.dll");
Type myRow = myAssy.GetType("DynaRow");
Type listType = typeof(List<>);
Type myListType = listType.MakeGenericType(myRow);
IList myTable = (IList)Activator.CreateInstance(myListType);
FieldInfo piT = myRow.GetField("t");
FieldInfo piVf = myRow.GetField("vf");
FieldInfo piIm = myRow.GetField("im");
ValueType aRow = (ValueType)Activator.CreateInstance(myRow);
int n = 0;
start = DateTime.Now;
while (n < 100000)
{
piT.SetValue(aRow, 1 * n);
piVf.SetValue(aRow, 2.0);
piIm.SetValue(aRow, 4.0);
myTable.Add(aRow);
n++;
}
end = DateTime.Now;
System.TimeSpan diff = end.Subtract(start);
label2.Text = diff.Seconds.ToString();
label4.Text = diff.Milliseconds.ToString();
dataGridView1.DataSource = myTable;
}
//create assy at runtime in memory
private void button4_Click(object sender, EventArgs e)
{
//build the assembly
Type myType = CreateDynRow();
Type listType = typeof(List<>);
Type myListType = listType.MakeGenericType(myType);
IList myTable = (IList)Activator.CreateInstance(myListType);
FieldInfo piT = myType.GetField("t");
FieldInfo piVf = myType.GetField("vf");
FieldInfo piIm = myType.GetField("im");
ValueType aRow = (ValueType)Activator.CreateInstance(myType);
int n = 0;
start = DateTime.Now;
while (n < 100000)
{
piT.SetValue(aRow, 1 * n);
piVf.SetValue(aRow, 2.0);
piIm.SetValue(aRow, 4.0);
myTable.Add(aRow);
n++;
}
end = DateTime.Now;
System.TimeSpan diff = end.Subtract(start);
label2.Text = diff.Seconds.ToString();
label4.Text = diff.Milliseconds.ToString();
dataGridView1.DataSource = myTable;
}
只是一個提示:DateTime的分辨率大約是15毫秒,所以當你使用DateTime.Now來計時的時候,兩個實際上執行得非常相似的事情可能會出現不同的長達15ms,只是由於舍入的略有不同邊界。因此,如果您的基準測試在15-30ms左右運行,則要麼運行更多迭代(以便15ms舍入誤差變得微不足道),要麼使用System.Diagnostics.Stopwatch等更高分辨率的計時器(後者稍微更方便一些API也是!)。 – itowlson 2009-12-21 19:43:10