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

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

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

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

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

我的问题是:

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

你有没有介绍你的程序?

您应该分析您的代码。 对象是快速的,不理想的代码是死的慢。

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

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

实例调用和静态调用之间的区别是如此微不足道,我很乐意下注它与您的性能问题无关。 完全没有。 是的,静态调用在技术上更快(通过微小的数量),但与您正在执行的所有文件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的电话时,我们仍然不到一秒钟!

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

正如alamar所说,你应该在进一步发展之前描述你的应用。 有一个免费的分析器可以从Microsoft获得,或者您可以使用JetBrains dotTrace分析器 。 当然还有其他的 – 那些是我用过的。

只是作为IO绑定或CPU绑定的指示 ,如果您在应用程序运行时运行任务管理器,该进程需要多少CPU? 磁盘是否一直在颠簸?

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

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

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

对于数字2,我非常怀疑使用静态方法会产生巨大的差异。 使用静态方法更快,但只是略微如此。 我们在这里谈论微秒。 可能还有其他事情要发生。 只有一种方法可以找到,就像alamar所说的那样,来分析你的代码。

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

我的答案是

  1. 根据您的操作系统和文件系统,在20 -30k文件/子文件夹之后性能开始下降。 这是生活中的事实。 Ntfs性能和大量文件和目录

  2. 非OO代码比OO代码更快的声明是严重的。 在分析代码之前,您无法知道性能瓶颈是什么。 有关良好信息,请参阅此问题的答案。 性能反模式

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

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

  1. 不知道你的FS就不可能回答这个问题。 但正如其他人所指出的,FS通常不会针对大量折叠目录树进行优化。
  2. 我认为由于可能 (你还没有描述)而拒绝OOP,速度增加10%是非常荒谬的,特别是当页面上写着“请不要太过于字面”。

最后,虽然你没有提供太多信息,但我认为没有理由认为这种“不平衡”是奇怪的。 写作速度较慢,有时甚至是如此。