2

I'm concerned about improving source code readability, and it involves reducing the size of huge methods by breaking them down into smaller (concise) methods. So, in a nutshell, let's say I have a very monolithic method that does a lot of different things, for example:

public void verHugeMethod(List<Person> people) {
    for (Person person : people) {
        totalAge += person.getAge();
        totalHeight += person.getHeight();
        totalWeight += person.getWeight();
        // More calculations over class variables...
    }
}

And I want to change the method to something like:

public void calculateTotalAge(List<Person> people) {
    for (Person person : people) {
        totalAge += person.getAge();
    }
}

public void calculateTotalHeight(List<Person> people) {
    for (Person person : people) {
        totalHeight += person.getHeight();
    }
}

public void calculateTotalWeight(List<Person> people) {
    for (Person person : people) {
        totalWeight += person.getWeight();
    }
}
// More calculations over class variables...

My concern is about performance (time and memory) when applying this kind of refactoring. For a small list of people, it's of course not a problem, but I'm worried about the asymptotic growth of this list.

For example, for a more old-fashioned for I can see the following impact:

// OPTION 1
public void method1() { // O(1) + O(3n)
    int i = 0; // O(1)
    while (int i < people.size()) { // O(n)
        doSomething(people.get(i)); // O(1)
        doAnotherThing(people.get(i)); // O(1)
        i++; // O(1)
    }
}

// OPTION 2
public void method1() { // O(2) + O(4n)
    method1(); // O(1) + O(2n)
    method2(); // O(1) + O(2n)
}
public void method2() { // O(1) + O(2n)
    int i = 0; // O(1)
    while (int i < people.size()) { // O(n)
        doSomething(people.get(i)); // O(1)
        i++; // O(1)
    }
}
public void method3() { // O(1) + O(2n)
    int i = 0; // O(1)
    while (int i < people.size()) { // O(n)
        doAnotherThing(people.get(i)); // O(1)
        i++; // O(1)
    }
}

I know how Java converts foreach directives to iterables. Therefore, my questions are:

  1. Does Java have some optimization in terms of execution or compiling?
  2. Should I be concerned with this kind of performance question?

Note: I know that in terms of asymptotic growth and Big-O notation we should ignore constants, but I'm just wondering about how this kind of scenario applies to Java.

João Pedro Schmitt
  • 1,046
  • 1
  • 11
  • 25

1 Answers1

5

If you complete the big-O analysis you will see that both options reduce to O(n). They have identical complexity!

They probably don't have the same performance, but complexity and complexity analysis (and Big-O notation) are not for measuring or predicting performance. Indeed, an O(n) algorithm may perform better than an O(1) algorithm for small enough values of n.


Does Java have some optimization in terms of execution or compiling?

Yes. The JIT compiler does a lot of optimization (at runtime). However, we can't predict if Options 1 and 2 will have equivalent performance.

Should I be concerned with this kind of performance question?

Yes and no.

It depends on whether / how much performance matters for your project. For many projects1, application performance is unimportant compared with other things; e.g. meeting all of the functional requirements, computing the correct answer all of the time, not crashing, not losing updates, etc.

And when performance is a concern, it is not necessarily the case that >this< snippet of code (out of the hundreds, thousands, millions of lines in the codebase) is worth optimizing. Not all code is equal. If this code is only executed occasionally, then optimizing it is likely to have a minimal effect on overall performance.

The standard mantra is to avoid premature optimization. Wait until you have the code working. THEN create a benchmark for measuring the application's performance doing actual work. THEN profile the application running the benchmark to find out which parts of the code are performance hotspots ... and focus your optimization efforts on the hotspots.


1 - The point is performance must be considered in the context of all the other requirements and constraints on the project. And if you spend too much time on performance too early, you are liable to miss deadlines, etcetera. Not to mention wasting effort on optimizing the wrong code.

Stephen C
  • 698,415
  • 94
  • 811
  • 1,216