我设计了一个C#控制台应用程序,使用OOP设计合并和拆分大文件(大小约为4GB)。它涉及读/写xml,平面文件和图像。我有读者和作家的课程。
合并时间约为00:12,而分裂时间超过04:30。然后我通过将输出文件分发到子目录而不是使用单个目录,将分割的性能提高到00:50。
我的老板要求我将所有内容转换为静态过程编程,而不是对象。他说00:12合并比较00:50分裂是不平衡的。他希望在00:30分钟完成分裂,转换为静态。
现在我知道根据this,静态调用会更快。但是我不同意所有静态都会更好,因为我必须在方法中使用“ref”和“out”参数。
我的问题是:
答案 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)
我的答案是
取决于您的操作系统和操作系统。文件系统,在20 -30k文件/子文件夹之后性能开始下降。这是生活中的事实。 Ntfs Performance And Large Volumes of files and directories
非OO代码比OO代码快的声明是重做的。在分析代码之前,您无法知道您的性能瓶颈是什么。有关详细信息Performance anti-patterns
答案 5 :(得分:0)
当目录中的条目数增加超过某个限制时,许多文件系统都会出现性能问题。你在用哪一个?
如果在程序的调试版本中添加日志记录功能,则可能会显示花费最多时间的位置。这就是优化应该发生的地方。
答案 6 :(得分:0)
最后,虽然你没有提供太多信息,但我认为没有理由认为这种“不平衡”是奇怪的。写作速度较慢,有时甚至是如此。