哪个有更好的表现?静态与对象

时间:2009-06-10 08:07:00

标签: c# performance oop static

我设计了一个C#控制台应用程序,使用OOP设计合并和拆分大文件(大小约为4GB)。它涉及读/写xml,平面文件和图像。我有读者和作家的课程。

合并时间约为00:12,而分裂时间超过04:30。然后我通过将输出文件分发到子目录而不是使用单个目录,将分割的性能提高到00:50。

我的老板要求我将所有内容转换为静态过程编程,而不是对象。他说00:12合并比较00:50分裂是不平衡的。他希望在00:30分钟完成分裂,转换为静态。

现在我知道根据this,静态调用会更快。但是我不同意所有静态都会更好,因为我必须在方法中使用“ref”和“out”参数。

我的问题是:

  1. 将文件拆分为子目录的原因比使用单个输出目录要快得多? (即大量文件> 200,000)
  2. 有没有比将代码从对象转换为静态更好的方法,以获得更高的性能?

7 个答案:

答案 0 :(得分:13)

您是否对自己的计划进行了介绍?

您应该分析您的代码。对象很快,没有最佳代码就慢了。

优化后,此任务无论如何都会受I / O限制(这意味着它花费大部分时间等待磁盘获取另一部分数据)。

是的,你的老板最好做一些专横的事情,比如打高尔夫球或者周围的事情,而不是告诉你关于软件设计的废话。 因为你不是想为他打高尔夫球,是吗?

答案 1 :(得分:12)

实例调用和静态调用之间的区别是如此微不足道,我很乐意下注它与您的性能问题无关。完全没有。是的,静态调用在技术上更快(通过微小的数量),但与您正在执行的所有文件IO相比,没有。正如已经说过的那样 - 描述你的代码,并且不要担心这样的事情(过早的优化)。最有可能的是,瓶颈是收集性能差,也许可以通过字典等进行修复。

时序:

static: 154ms
instance: 156ms

超过50M的呼叫有2ms的差异!算了吧......

基于:

class Program
{
    static void Main()
    {
        StaticMethod(); // JIT
        Program p = new Program();
        p.InstanceMethod(); // JIT

        const int LOOP = 50000000; // 50M
        Stopwatch watch = Stopwatch.StartNew();
        for (int i = 0; i < LOOP; i++) StaticMethod();
        watch.Stop();
        Console.WriteLine("static: " + watch.ElapsedMilliseconds + "ms");

        watch = Stopwatch.StartNew();
        for (int i = 0; i < LOOP; i++) p.InstanceMethod();
        watch.Stop();
        Console.WriteLine("instance: " + watch.ElapsedMilliseconds + "ms");
    }
    [MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.NoOptimization)]
    void InstanceMethod() { }
    [MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.NoOptimization)]
    static void StaticMethod() { }
}

编辑:

如果我们假设(例如)我们每20次调用(if (i % 20 == 0) p = new Program();)创建一个新方法,则指标会更改为:

static: 174ms
instance: 873ms

再次 - 远远不足以表明瓶颈,当超过50M的电话时,我们仍然不到一秒钟!

答案 2 :(得分:6)

你的任务听起来应该绝对是IO绑定的,而不是CPU绑定的。通过去除适当的OO设计进行微观优化将是疯狂的。无论如何,静态方法和实例方法之间的区别通常是不可测量的(如果它甚至存在)。

正如alamar所说,你应该在继续之前对你的应用进行分析。有free profiler available from Microsoft或您可以使用JetBrains dotTrace profiler。当然还有其他的 - 那些是我用过的两个。

就像指示它是IO绑定还是CPU绑定一样,如果你在应用程序运行时运行任务管理器,那么进程需要多少CPU?磁盘一直在颠簸吗?

将大量文件放在目录中会降低对该目录的访问速度,但只有在实际创建或打开文件或列出目录中的文件时才会这样。诚然,我很惊讶它确实产生了很大的不同。但是,无论如何,在目录中拥有200,000个文件听起来相当难以管理。在使用这些文件之后,使用分层方法可能会更好。

为什么你的老板认为合并和拆分首先要花费相同的时间?

答案 3 :(得分:3)

我可以回答1:在一个目录中有很多文件会让你性能不佳。它与你的代码没有任何关系 - 它是Windows的东西(或NTFS的东西,我不知道)。在不同的子目录下拆分确实可以大大提高性能。

对于数字2,我高度怀疑使用静态方法会产生巨大的差异。使用静态方法更快,但只有略微。我们这里谈的是微秒。可能还有别的事情发生了。只有一种方法可以找到答案,就像alamar所说的那样,可以分析你的代码。

您可以使用Ants之类的工具来分析您的代码并查看哪些操作是瓶颈。它可以列出程序中所有方法所花费的时间,因此您可以看到花费最多时间的内容,这可能是真正的任何内容。但至少你知道要优化什么。

答案 4 :(得分:2)

我的答案是

  1. 取决于您的操作系统和操作系统。文件系统,在20 -30k文件/子文件夹之后性能开始下降。这是生活中的事实。 Ntfs Performance And Large Volumes of files and directories

  2. 非OO代码比OO代码快的声明是重做的。在分析代码之前,您无法知道您的性能瓶颈是什么。有关详细信息Performance anti-patterns

  3. ,请参阅此问题的答案

答案 5 :(得分:0)

当目录中的条目数增加超过某个限制时,许多文件系统都会出现性能问题。你在用哪一个?

如果在程序的调试版本中添加日志记录功能,则可能会显示花费最多时间的位置。这就是优化应该发生的地方。

答案 6 :(得分:0)

  1. 如果不知道你的FS,就不可能回答这个问题。但正如其他人所指出的,FS通常不会针对大量折叠目录树进行优化。
  2. 我认为由于可能而拒绝OOP(你还没有描述)~10%的速度增加是荒谬的,特别是当页面上写着“请不要太过于字面意思”。
  3. 最后,虽然你没有提供太多信息,但我认为没有理由认为这种“不平衡”是奇怪的。写作速度较慢,有时甚至是如此。

相关问题