我最初采用Java中的gung ho方法来推导所有内容,每次最小化属性的使用和动态计算方法。但是对于较大的数据集,我开始遇到性能问题,并且多次调用相同的方法只计算相同的结果似乎是多余的,有时会对性能产生指数拖累。
我终于开始采用数据密集型操作的方法来设置我的方法,以便仅在第一次调用时计算并保存结果以用于将来的任何返回。
这是不好的做法吗?
答案 0 :(得分:6)
一次计算方法并保存结果是不好的做法吗?
这个 1 没有正确的一般答案。这取决于具体情况。
它(IMO)不良做法在任何地方做这个习惯。 JIT编译器能够进行各种自动优化,使得这种手优化毫无意义......甚至是有害的。 (一般来说,手动优化是不值得的,除非您使用真实的输入数据分析完整的应用程序,并且分析告诉您在代码中的特定点有一个性能热点。)
如果你习惯这样做(即没有思考),你可能会使你的代码不那么可读,并且可能使代码变慢而不是更快。如果您每次编写方法调用时都在考虑它,那么这将影响您的工作效率。
当您有充分的理由相信方法调用可能很昂贵时,执行此操作不差练习。但是,请考虑您的直觉可能是错误的,并且依靠分析来告诉您在哪里花费您的努力可能会更好。 (见上文关于生产力的说明。)
如果您已确定性能是基于应用程序级基准测试的真正关注点,则执行此操作良好做法,并且您已通过分析确定这些调用的手动优化是必要的。
如果该方法有副作用且您不希望副作用发生两次,则必要。
不正确如果该方法有副作用,您每次都需要产生副作用。
要考虑的另一件事是这是否有助于或阻碍可读性......以及可维护性对于您的项目是否比性能更重要或更不重要。
1 ...并且声称存在的答案过于概括和/或过于教条。说真的,不是那么简单。
答案 1 :(得分:5)
首先,如果您正在计算数据并再次执行此操作,那么您确实在Java中犯下了巨大的罪行。正如您所说,我们必须最大限度地减少内存使用,并且计算需要大量内存。
其次,首次计算操作并将其保存在变量中是最佳做法之一。下次再次需要该值时,只需调用变量。
答案 2 :(得分:3)
不,不是,如果您遇到性能问题,这是一个很好的做法。但是,如果不这样做,可能会被视为过早优化。该优化技术称为Memoization。
答案 3 :(得分:1)
一般的答案是函数是否正在做一些阻止编译器确定它将始终返回相同结果的东西。例如,该功能是从磁盘或网络读取外部数据。
如果编译器无法从根本上确定这种“不可变”行为,那么您应该存储并重用任何此类调用的结果。
如果编译器确实可以确定(至少在原理上)结果是相同的 - 例如,计算第n个Fibonacci数的函数 - 那么它取决于编译器的复杂程度。功能编程语言,尤其是Haskell是专门设计的,除了少数例外之外的所有函数都保证为相同的参数返回相同的值,因此所有实现都会自动执行这样的缓存。
但是,如果语言没有这样设计,其中Java就是其中之一,编译器极不可能确定您的Fibonacci代码是“不可变的”可以这么说。因此,您应该自己存储和重用该值。
最后需要注意的是,为计算百分比的函数(例如计算百分比的函数)执行此操作不值得额外复杂。
更新:您的问题似乎是不是否存储和重用函数返回的值,但函数本身是否保留内部缓存。这个,我建议反对除了从不同的代码区域调用的已识别的热点,并且这些代码区域没有简单的方法可以相互协调。这是因为缓存这些值有一些缺点 - 你可能会浪费一些内存来缓存可能实际上不再需要的值;更糟糕的是,这些价值观可能会逐渐消除最终需要的价值观;第三,有额外的指令和内存访问来检查一个值是否在缓存中。
存储和重用的逻辑最好保留在函数之外,以便它可以比缓存更精确地存储和重用。