4

I just realized that I have no idea on how to tell whether or not a piece of Java code is efficient from the computational point of view. Reading several source codes sometimes I feel that the code I'm reading is highly inefficient, some other times I feel the opposite.

Could you list the basic one-line rules to respect and why they are so important?

edit - My question is related to the Java implementations of the JVM, so things like Java allocation issues, String management, exception handling, thread synchronization and so on.

Thanks in advance

p.s. don't take the "one-line" literally pls

Jack
  • 1,066
  • 2
  • 10
  • 22

5 Answers5

8

Basic one-line rule? Okay, here you go:

Avoid unnecessary computations.

How do you do it? Sorry, no one-line answer to that. :(

Well, people spends years in college learning about algorithms and data structures in computer science for a reason... might want to take a course on algorithms/data structures sometime.


I'm not sure what you mean by "from a computation point of view" (it seems to imply algorithm issues), but assuming you mean tricks more similar to things like profiling, try these:

  • Run the program, then suddenly pause it, and see where it paused. Do this a few times; wherever it stops the most is a bottleneck, and how often it stops indicates how bad of a bottleneck it is.

  • Avoid boxing/unboxing (converting between int and Integer, etc.); especially avoid Integer[], List<Integer>, and other things that internally store arrays of objects of primitive types

  • Factor out common code (sometimes a speed issue, sometimes readability)

  • Avoid looping with String operations; use StringBuilder/StringBuffer instead. (In short, avoid creating and/or copying data when that's not needed.)

I'll add to this if other things come to mind.

user541686
  • 205,094
  • 128
  • 528
  • 886
  • I'm not talking about ads, my question is more related to the language/JVM and operating system. There are lots of discussions about the Java allocation issues, string management, exception handling, thread synchronization and so on. (p.s. I'm one of those who spent years in college, also learning ads) – Jack May 22 '11 at 07:29
  • @Jack: Sorry but your question definitely didn't convey that information, so we couldn't see where you're coming from. It's still a bit vague, though; not sure how much help you'll get but good luck! – user541686 May 22 '11 at 07:33
  • @Mehrdad: You are right, I was too concise. I'll edit the question. – Jack May 22 '11 at 07:35
  • By "from a computational point of view" I meant the specific optimization of "speed" as opposed to other optimizations like memory consumption or code size – Jack May 22 '11 at 08:02
  • @Jack: +1 When you pause it, look at each line of code on the stack. The "bottleneck" (I prefer "drain") could be any one of those lines. Also, don't confuse "looks inefficient" with "is inefficient". That's a mistake newbies make. – Mike Dunlavey May 23 '11 at 13:08
  • @Mike: Once again, I'm not so newbie so please opt for more constructive answers than "avoid unnecessary computation". I'm just trying to figure out what are the constructs that introduce latency in the code. Moreover, I think I was clear that my question was related to the fact that what I think it "looks" inefficient at the end it is not (and vice versa). If you see the question I marked as an answer, that's what I was looking for. – Jack May 24 '11 at 06:50
  • Furthermore, I don't consider "pause the program" as a solution for benchmarking an application, in fact it does not tell anything about the real efficiency and it lacks of scientific methodology. A better solution in my opinion are Java profilers and ad-hoc solutions like AOP for small portions of the code. But still, that's not what I was looking for... (p.s. of course I'm not criticizing you, I had to be more specific on the description of my question) – Jack May 24 '11 at 06:56
  • @Jack: Take a look at [this answer](http://stackoverflow.com/questions/4832642/when-is-optimization-premature/4832698#4832698), which had quite some support. Pausing is actually a **very** well-founded way of benchmarking speed, and in fact it's using very basic statistics to come up with results that are sometimes very hard to get with profiling. (E.g., try profiling individual instructions; it won't work.) – user541686 May 24 '11 at 07:04
  • @Jack: Didn't mean to sound negative, sorry, and I agree that pausing is not good for benchmarking - what it's good for is finding what to optimize. (Those are not the same.) For that purpose, the [scientific methodology is outlined here](http://stackoverflow.com/questions/4387895/if-profiler-is-not-the-answer-what-other-choices-do-we-have/4390868#4390868), and if you carefully read the gprof paper you will see how thin its justification is, and most profilers are based on that measurement paradigm. – Mike Dunlavey May 24 '11 at 12:28
  • 1
    @Jack: BTW, the literature basis for profiling is remarkably slim. Here's the [gprof paper](http://stackoverflow.com/questions/6087065/what-is-dynamic-program-analysis-and-its-principles-literature-on-dynamic-progra/6088490#6088490) from SIGPLAN. I (humble cough) wrote [SIGPLAN & Dr. Dobbs papers](http://stackoverflow.com/questions/6087065/what-is-dynamic-program-analysis-and-its-principles-literature-on-dynamic-progra/6088490#6088490). From my point of view, the reason the lit is slim is that the subject is actually very simple. – Mike Dunlavey May 24 '11 at 12:35
  • @Mike: I appreciated the pointers, I'll read them up and I'll let you know. – Jack May 26 '11 at 15:52
  • @Jack: My favorite edge case is an infinite (or nearly) loop. You can measure it if you want to wait. A single stack sample will not measure it, but will find it. Also, [here's an example](http://stackoverflow.com/questions/5525758/function-profiling-woes-visual-studio-2010-ultimate/5560023#5560023) that illustrates the issues with an artificial program. – Mike Dunlavey May 26 '11 at 16:14
7

Use profiling. Look at JProfile or for any other profilers.

Roman
  • 64,384
  • 92
  • 238
  • 332
  • @Mehrdad: I'm talking about professional software development where profiling is often very useful to find out where the bottleneck. If we are talking about algorithms complexity, then, of course, profiling has nothing to do with that, but why do we need `java` tag in this thread then? – Roman May 22 '11 at 07:28
  • Thank you Roman, that's exactly what I do right now and it helps a lot. However, sometimes doing profiling is very time consuming and I was aiming more at the recurring problems and solutions you find using profiling. – Jack May 22 '11 at 07:33
4

I'll second Mherdad's answer in that there definitely are no "basic one-line rules."

Regarding answers that suggest using profiling tools, profiling isn't really useful until you understand algorithmic time complexity and big-O notation. From wikipedia's article on Big O notation:

In mathematics, computer science, and related fields, big-O notation describes the limiting behavior of the function when the argument tends towards a particular value or infinity, usually in terms of simpler functions. Big O notation characterizes functions according to their growth rates: different functions with the same growth rate may be represented using the same O notation.

The idea behind big-O notation is that it gives you a feel for how input size affects execution time for a given algorithm. For instance, consider the following two methods:

void linearFoo(List<String> strings){
    for(String s:strings){
      doSomethingWithString(s);
    }
}

void quadraticFoo(List<String> strings){
    for(String s:strings){
        for(String s1:strings){
            doSomethingWithTwoStrings(s,s1);
        }
    }
}

linearFoo is said to be O(n), meaning that its time increases linearly with the input size n (ie. strings.size()). quadraticFoo is said to be O(n2), meaning that the time it takes to execute quadraticFoo is a function of strings.size() squared.

Once you have a feel for the algorithmic time complexity of your program profiling tools will start to be useful. For instance, you'll be able to tell that if while profiling you find out that a method typically takes 1ms for a fixed input size, if that method is O(n), doubling the input size will result in an execution time of 2ms (1ms = n, therefore 2n = 2ms). However, if it is O(n2), doubling input size will mean that your method will take around 4ms to execute (1ms = n2 therefore (2n)2 = 4ms).

Ben Burns
  • 14,978
  • 4
  • 35
  • 56
3

You can use jconsole for monitoring your application's deadlocks, memory leaks, threads and heap. In short you can see your applications performance in graphs.

enter image description here

Searock
  • 6,278
  • 11
  • 62
  • 98
3

Take a look at the book Effective Java by Joshua Bloch if you really need a list of rules that you should follow in Java. The book offers guidelines not just for performance but also not he proper way of programming in Java.

aseychell
  • 1,794
  • 17
  • 35
  • 1
    The book you linked, together with what I found on http://www.cs.cmu.edu/~jch/java/speed.html, I think answer my question – Jack May 22 '11 at 08:03
  • welcome Jack :) its definitely a good book and improves the way you look at Java programming – aseychell May 22 '11 at 08:34