我想知道消耗对象值的性能方面的最佳方法。我已经看到了缓存值并在后面部分使用的代码。它在使用方面看起来很干净。性能明智哪个更好,为什么。这可能是一个简单的问题,但我相信很多人都想知道答案。
以下是示例代码。
//Class with variables
Cls A
{
String a = "aaa";
String b = "bbb";
String c = "ccc";
}
//Cls B with Cls A object and initialized
Cls B
{
A a1 = new A();
}
**One**
B b1 = new B();
Str t1 = b1.a1.a;
Str t2 = b1.a1.b;
**Two**
B b1 = new B();
A c1 = b1.a1;
Str t1 = c1.a;
Str t2 = c1.b;
堆叠或堆叠是否会发挥作用
答案 0 :(得分:1)
在此特定情况下,它们可能是等效的,因为a1
是一个字段。
一般来说,如果a1
是一个属性,你就不知道它是如何“支持”的(它保存了值)。
如果它将其值保存在字段上,那么访问该属性几乎/快于缓存其值。如果必须每次/必须访问Dictionary
/其他复杂对象时计算其值,那么可以更好地缓存它。
在ASP.NET中,a1
通常可以是Session[...]
/ ViewState[...]
个对象(最后它们就像Dictionary
一样,所以它们以类似的方式工作 - 明智的),所以如果你在紧张的for
或while
周期中访问它,有时最好“缓存”它的值。
一般来说,这是过早的优化。除非你需要,否则你不会这样做。
举一些经典的例子:
public class MyClass {
// A field
public int Fast1;
// An automatic property backed by a field
public int Fast2 { get; set; }
// A property backed by a field
public int Fast3 {
get { return Fast1; }
}
// Each time you call this property, some calculation is done
public int LittleSlow1 {
get {
int j = 0;
for (int i = 0; i < 1000000; i++) {
if (i > j) {
i = j;
}
}
return j;
}
}
// This property is backed by a collection. There is a
// scan of the collection to retrieve the value.
public int LittleSlow2 {
get {
return ignoreme["LittleSlow1"];
}
}
public Dictionary<string, int> ignoreme = new Dictionary<string, int>();
}
反对属性的一个原因是它们与myprop = 5
或x = myprop + 1
中使用它们的方式几乎完全相同,但是就这种方式而言,它们“隐藏”给程序员潜在的成本使用它们,而当程序员调用方法时,他知道该方法可能很昂贵。
答案 1 :(得分:0)
为此,一个好的旧基准可以定量地给你你想要的东西。
测试方法
class A {
public string a = "aaa", b = "bbb", c = "ccc";
}
class B {
public A a1 = new A();
}
class Program {
static void Main(string[] args) {
int counter = 0;
int counter2 = 0;
Stopwatch sw = new Stopwatch();
// Method 1
sw.Start();
B b1 = new B();
while (sw.ElapsedMilliseconds < 5000) {
string t1 = b1.a1.a;
string t2 = b1.a1.b;
counter++;
}
sw.Stop();
sw.Reset();
// Method 2
sw.Start();
B b2 = new B();
A c1 = b2.a1;
while (sw.ElapsedMilliseconds <5000) {
string t3 = c1.a;
string t4 = c1.b;
counter2++;
}
sw.Stop();
Console.WriteLine("Counter={0}", counter);
Console.WriteLine("Counter2={0}", counter2);
Console.ReadKey();
}
}
我测试两种方法5秒钟为属性赋值。
注意:这可以设计得更好,但这仍然会给我们提供合理准确的结果。
在此之后运行5次,结果如下:
输出(注意:我们测量哪种方法的执行次数越多越好越好)
Counter=33054729
Counter2=33783643
Counter=32599924
Counter2=33610612
Counter=52581701
Counter2=53822872
Counter=50725227
Counter2=51932970
Counter=32688454
Counter2=32577850
正如您所看到的,结果相对接近,但第二种方法整体似乎更快。可能的解释可能是在property
内调用方法的开销成本。如果其他人可以提供更好的解释,请告诉我。