泛型与C#澄清中的对象

abh*_*vce 0 c#

我试图用类似的实现创建类.一个在构造函数中使用装箱/拆箱,而另一个使用泛型.

然后尝试为这两个类创建对象1,000,000次.当我首先为Obj类运行'for循环'时,我总是会有更长的时间来创建Obj,但是当我为Gen类运行'for循环'时,75%的时间我会为Obj获得更长的时间.请帮帮我这个行为.这是代码: -

    class Obj
{
    public string _t;
    public int _u;

    public Obj(Object t, Object u) //Boxing taking place implicitly
    {
        _t = (string)t; 
        _u = (int)u; //unboxing
    }
}
class Gen<T, U> 
{
    public T _t;
    public U _u;

    public Gen(T t, U u)
    {
        _t = t;
        _u = u;
    }
}
static void Main(string[] args)
    {
        long before_Obj = DateTime.Now.Ticks;
        for (int i = 0; i < 1000000; i++)
        {
            new Obj("hi", i);
        }
        long after_Obj = DateTime.Now.Ticks - before_Obj;
        Console.WriteLine(after_Obj);

        long before_Gen = DateTime.Now.Ticks;
        for (int i = 0; i < 1000000; i++)
        {
            new Gen<string, int>("hi", i);
        }
        long after_Gen = DateTime.Now.Ticks - before_Gen;
        Console.WriteLine(after_Gen);
    }
Run Code Online (Sandbox Code Playgroud)

输出:2656250 1406250

Eri*_*ert 10

这是一个设计糟糕且执行不佳的测试,这可能是你得到奇怪结果的原因.考虑一下测试设计不当的一些方法.

1)您将抖动成本与常规成本混为一谈.对于每种方法,抖动仅运行一次,但运行抖动可能非常昂贵,特别是与非常简单的方法(如这些)的成本相比.我已经看到了基准测试,其中抖动成本主导了每次后续运行的成本.开始测量循环之前,您应该至少运行一次测试场景.

2)DateTime旨在测量"午餐时间"的时间,而不是亚微秒级的时间.始终使用秒表作为高精度计时器.

3)第一次测试创建了200万个对象 - 一百万个"Obj"和一百万个盒装整数.这意味着在第二次测试运行时垃圾收集器可能有多达两百万个对象要处理,然后分配另外一百万个对象.如果这触发了一个集合,那么第一次测试会产生第二次测试的费用!如果我们测试我们两个中的哪一个可以更快地制作蛋糕,我先去离开凌乱的厨房让你清理,当然你会慢下来.

而且,第二个测试创建了另外一百万个对象,但是可能垃圾收集器在测试完成之后才会运行; 现在你已经花了本应该收取第二次测试的费用而且没有在任何地方考虑到它.

要么编写两个不同的程序,要么一个的GC成本不向另一个计费,要么在每次测试后强制完全收集,并将测试的收集成本收费.记住,拳击的成本不仅仅是分配和复制; 这也是收集压力和清理.

4)测试不是现实世界,它会产生各种各样的问题.您正在创建数百万个对象,这意味着程序成本的很大一部分将处理由所有这些对象引起的收集压力.这是现实的吗?在一个真实的程序中,你可能不会创建数百万个这些对象,而其他一些因素可能会产生收集压力.

5)对于任何创建的对象都没有任何用处; 仅为了观察创建和收集它们所需时间的副作用而创建对象.抖动被允许实现这一事实 - 它可以进行流量分析并确定从未观察到ctor调用的结果,并且忽略整个事件,将其成本降低到零.显然它不会在这里这样做,但它可能在其他版本的抖动中.我已经看到很多性能测试,其中人们断定X比Y快得多,实际上X的成本为零,因为抖动完全消除了从未观察到的计算.

当然,它应该不言而喻 - 但遗憾的是它不会 - 在任何情况下都不会在调试器中运行您的测试程序.因为那时您正在测量运行调试器的成本与运行程序的成本一样多.抖动会对调试器中运行的程序进行去优化,以使其更易于调试.在现实条件下测试; 您的客户不会在调试器中运行您的程序,因此您的性能测试也不应该在调试器中运行.

  • @abhishekrvce,你应该测量Release版本,但这还不够.正如Eric所说,你*也必须在没有调试器的情况下运行(使用Ctrl + F5,而不是VS中的F5). (2认同)