软件开发中的一个常见规则是,一旦部署了公共API,尤其是,如果你已经记录了这个API(是的,你应该有),你必须要长时间思考并且在进行任何可能破坏与该API的向后兼容性的更改之前很难,因为此类更改将中断更改。事实上,我相信很多开发人员会争辩说,不管你有多长时间难以理解,你都应该完全放弃它。
有时,开发人员会实际记录方法的性能。许多MSDN文档都是这样做的,例如,使用Big O notation。更改此还会构成“破坏性”变化吗?也许这不是一个明确的问题;换句话说:应该避免吗?
在我看来,如果您可能已经开发出一种优越的算法来解决问题,如果您之前已经证明该算法是O(N 2 ),那么您可能会原谅改进你的API,取而代之的是这个优越的算法,比如O(log N)。您的API用户可能会注意到这一点,我想,只会觉得很有待改进。
另一方面,我想知道,由于其他原因恶化 API组件的性能是否会被认为是“可以原谅的” - 例如,您针对最常见的用例进行了优化在一般情况下导致表现更差;您在CPU周期内优化内存,反之亦然;你消除了导致其他问题的外部依赖等等。
我的直觉告诉我,提高性能几乎可以肯定。对面怎么样?是否可以,假设您更新了文档?这是错的吗?我只是在寻找一些合理的指导方针。
答案 0 :(得分:1)
好吧,如果你的表现更好,我怀疑你会得到任何抱怨。
否则,我会说这取决于。如果您可以访问所有客户的源代码,那么正确的做法就是仔细查看它们并确认您的更改不会给它们带来任何麻烦。
如果它比这更复杂,并且您可能会使某些用例的性能显着恶化,那么您应该与您的客户交谈,并警告他们这一变化。
如果你不能这样做(例如:某种收缩包装的API),那么,最好将更改作为替代呼叫或其他东西来实施,并留下旧的呼叫。
答案 1 :(得分:1)
突破性变化是违反规范的。
因此,如果您正在处理一个软件,其中指定了时间(平均情况,最坏情况,方差或其他)或渐近行为,您应该避免破坏它。我相信这种规范应该是任何项目的一部分,如果你有实时的依赖关系,他们肯定会在那里。
只要功能得到尊重,您就可以自由地提高性能,我想没有人会抱怨。
对于恶化表现,(再次在规格和合理原因范围内)取决于选择的平衡影响。这是一种权衡,因此应根据具体情况进行分析。如果您的处理时间影响可能会因未被注意到激怒的用户而异,那怎么可能是一般规则呢?
答案 2 :(得分:1)
我注意到C ++标准要求STL的某些功能的性能不比给定的Big-O差。
我从经验中说,如果您正在执行具有大量数据集的长持续时间批处理(2-3小时,N~10 7 ),则无意中O(N 2 )可能是不可接受的。如果一个重要的依赖API将其性能从O(N)改为O(N 2 ),这样的程序可以将其计算时间大大延长(2小时的计算时间可能会变成4000年计算时间)该程序将被视为破碎。所以,我认为Big-O表现的恶化是一个突破性的变化。
答案 3 :(得分:1)
如果您将实施文档记录为big-O,那么提高实施性能是正常的。如果您的新实现是O(log n),那么也 O(n ^ 2),如文档所述。相反,放宽限制是用户POV的突破性变化(因为前一个属性不再是真的)。
因此,为了在将来允许更好的算法,不要将性能记录为大-Theta。在任何情况下,保证对我来说似乎很愚蠢,任何操作至少需要一定的时间,除非您发布CPU操作码的循环计数,从设备中断频率,或者类似的硬件级别的东西,确切的时间是重要的。只是不要指定一个最小值,如果用户来找你说“我们真的需要保证下限时间复杂度”,那么写一个替代的功能接口:
int myfunc_omega_n_squared(n, args) {
sleep(n*n); // well, actually in a loop because of spurious wakes
return myfunc(n, args);
}
他们可以调用此而不是myfunc
,并解决他们特有的问题; - )
请注意,如果您要定义其他人可能实现的接口(可能与您自己的实现一样),那么将接口更改为更严格的复杂性要求当然是一个重大变化实施者的POV,因为他们以前有效的实施不再是。
它会告诉您这些变化是否会因记录的内容而中断。然而,几乎不可思议的是,任何人都会在实现的渐近复杂性上依赖仅,而不是实际的运行时。荒谬的例子,但是如果你从需要一个小时来处理100GB输入数据的O(n ^ 2)变成一个需要一周时间来处理100GB数据的O(log n),你可能会得到处理100GB数据的任何用户的投诉,无论您实际上没有破坏您的显式界面。
API用户想要的是他们的代码仍能正常工作,所以一般情况下,如果你要做一些慢得多的东西,无论它是否大于O,那么最好还是有充分的理由。如果可能的话,我想发布一个新的界面,而不是撤回和替换旧界面。