Calling the function twice vs. storing the output and using it in Java

偶尔善良 提交于 2019-12-12 01:36:26

问题


Suppose that I have a boolean function isCorrect(Set<Integer>).
The parameter of the function is calculated by another function buildSet().

Which one is better in terms of both time and space efficiency?

Set<Integer> set = buildSet();
if(isCorrect(set))
    doSomethingWith(set);

or

if(isCorrect(buildSet()))
    doSomethingWith(buildSet());

回答1:


The first approach is better, and I don't think this is a matter of opinion. Don't call the same function twice wastefully when you already have its result. Of course, I'm assuming buildSet() doesn't have any necessary side effects.

Which one is better in terms of both time and space efficiency?

In terms of time, you're building the set once in the first snippet and twice in the second snippet, so presumably the second would take longer. In terms of space, there likely will not be a difference. However, you seem to be instantiating two objects in your second snippet and just one in your first (again, I can't be sure of this because I don't know how buildSet() is implemented). If this is the case and you're retaining both of those objects, then the second snippet will use twice the space as well.




回答2:


The answer is - it depends. See below:

  • If function call is time-consuming, you definenetely should store the result;
  • Storing the result might make the code a little bit less readable, although readability is not an objective metric;
  • Sometimes you may want to be sure, that first and second usage deals with exactly the same object. When you call function twice, you may get different results. This situation is usually called race condition or data race and in most cases it affects program correctness.

So, to summarize: in most cases it makes sense to store the result. Sometimes (but IMO not too often) it is not really neccesary.




回答3:


While the existing answers give good reasons why storing the value is best, they miss out on what I feel is an important one (in fact, the most important one): in your second example (running the function twice), you introduce a potential race condition.

If buildSet() relies on outside factors (which is highly probable in any non-trivial function - and could become true with later changes), there is a chance that the value changes between the if check and the second call. This could create a subtle and hard to find bug, which would potentially only become visible when you made changes elsewhere, or certain events happened with specific timings.

This is, by itself, a good reason to avoid such a pattern.




回答4:


By going from the second example (two calls) to the first (one call), you will save the time that the second call to buildSet is on the stack. If that call is on the stack 10% of the time, then your speedup will be a factor of 100/90 = 1.11, or 11%. If it is on the stack 50% of the time, the speedup will be a factor of 100/50 = 2, or 100%.

How do you know what fraction of time a function call is on the stack?
It is inclusive wall-clock percent by line.

Not every profiler will tell you this.

  • If it only tells you "self time", not inclusive time, that will not tell you anything about the time spent in a function call.
  • If it only tells you by function, not by line, you can't tell if the second call was the problem (as opposed to the first).
  • If it is only a "CPU-profiler", then if there is any I/O, sleep, or lock wait in the buildSet function or elsewhere in the app, the profiler will act like it doesn't exist.
  • If it does not tell you percent, but only milliseconds or call counts, then you gotta do the math to figure out what the percent of total time in the call is.
  • Call graphs don't tell you, "flame graphs" don't tell you, timelines don't tell you, etc. etc.

One that does tell you is Zoom. Others may, if you can figure out how to tell them what to do. The method I and many people use is random pausing.



来源:https://stackoverflow.com/questions/23712410/calling-the-function-twice-vs-storing-the-output-and-using-it-in-java

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!