views:

234

answers:

3

Hello,

my question is about two possible ways to access data:

(My question is about "real life usage" of java statements like below, accessing the data 2-10 times in a function. Not iterating over such statements with thousands of iterations/calls.)

System.out.println(request.getParameter("locale"));
System.out.println(request.getParameter("locale"));
System.out.println(request.getParameter("locale"));
System.out.println(request.getParameter("locale"));
System.out.println(request.getParameter("locale"));

versus

String localeString = request.getParameter("locale");
System.out.println(localeString);
System.out.println(localeString);
System.out.println(localeString);
System.out.println(localeString);
System.out.println(localeString);

Which example is the "fastest/most efficient" one? (Is the second one faster at all? As there is the variable assignment on top of the five println statements that will also consume CPU cycles...)

Does the Java Compiler optimize the code in example 1 so that it looks like the second example in the Bytecode? (=Doing any optimization by myself in the code is not necessary at all).

Is the navigation of the Object graph (as used in example 1) in terms of CPU cycle more costworthy compared to directly reading a variable (example 2)?

Thank you very much

+2  A: 
  1. In terms of performance, this seems like a micro-optimization, that really doesn't make much difference in the scheme of things. The time to call getParameter() a few more times will of course be far overshadowed by network latency and other factors.

  2. The specific timing difference depends on the implementation of getParameter() - if it really makes a difference to you, you should measure with your particular servlet container.

  3. The second option has advantages that go beyond performance:

    a. Readability: it is clearer having one name for a variable than resolving it each time.

    b. Maintainability: if the name of the parameter changes, you will only have to change one place. In general, it is better to avoid duplicating even short expressions.

    c. Correctness: you can check that the parameter has a value (i.e. not null) and is in the correct range at one point when you first get it. After this, use the variable, which you know is correct. Also, if you need to do cleaning (e.g. to avoid SQL injection), you can do it in one place.

Avi
+2  A: 

I don't think the compiler or JVM can deduce your second example from the first one -- it would have to know for sure that the result of those calls getParameter() never changes (another thread might step in and change it), and also that the method does not have any side-effects.

Generally speaking calling a method always has a little overhead, so your second example is faster in that sense. However, as Avi already suggested, 'optimizing' for style/readability is a better rationale for choosing the second option over the first one. Optimizing for speed only starts making sense if you really do a lot of calls, or if the call is very expensive -- both are probably not the case in your current example.

Simon Groenewolt
Hello Simon, thank you very much for your answer. Unfortunately I can mark only one answer as solved. But your answer was also very informative. Thank you very much!
jan
A: 

The prior posters are right, this is micro-optimization. But it is still sort of interesting to take a look occasionally. Running javap just takes a second.

javap -c -classpath . VariableAssignmentTest

public class VariableAssignmentTest extends javax.servlet.http.HttpServlet{                                                                             
protected void doGet1(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)   throws javax.servlet.ServletException, java.io.IOException;
  Code:                                                                                                                                                           
   0:   getstatic       #2; //Field java/lang/System.out:Ljava/io/PrintStream;                                                                                    
   3:   aload_1                                                                                                                                                   
   4:   ldc     #3; //String locale                                                                                                                               
   6:   invokeinterface #4,  2; //InterfaceMethod javax/servlet/http/HttpServletRequest.getParameter:(Ljava/lang/String;)Ljava/lang/String;                       
   11:  invokevirtual   #5; //Method java/io/PrintStream.println:(Ljava/lang/String;)V                                                                            
   14:  getstatic       #2; //Field java/lang/System.out:Ljava/io/PrintStream;                                                                                    
   17:  aload_1                                                                                                                                                   
   18:  ldc     #3; //String locale                                                                                                                               
   20:  invokeinterface #4,  2; //InterfaceMethod javax/servlet/http/HttpServletRequest.getParameter:(Ljava/lang/String;)Ljava/lang/String;                       
   25:  invokevirtual   #5; //Method java/io/PrintStream.println:(Ljava/lang/String;)V                                                                            
   28:  getstatic       #2; //Field java/lang/System.out:Ljava/io/PrintStream;                                                                                    
   31:  aload_1                                                                                                                                                   
   32:  ldc     #3; //String locale                                                                                                                               
   34:  invokeinterface #4,  2; //InterfaceMethod javax/servlet/http/HttpServletRequest.getParameter:(Ljava/lang/String;)Ljava/lang/String;
   39:  invokevirtual   #5; //Method java/io/PrintStream.println:(Ljava/lang/String;)V
   42:  getstatic       #2; //Field java/lang/System.out:Ljava/io/PrintStream;
   45:  aload_1
   46:  ldc     #3; //String locale
   48:  invokeinterface #4,  2; //InterfaceMethod javax/servlet/http/HttpServletRequest.getParameter:(Ljava/lang/String;)Ljava/lang/String;
   53:  invokevirtual   #5; //Method java/io/PrintStream.println:(Ljava/lang/String;)V
   56:  getstatic       #2; //Field java/lang/System.out:Ljava/io/PrintStream;
   59:  aload_1
   60:  ldc     #3; //String locale
   62:  invokeinterface #4,  2; //InterfaceMethod javax/servlet/http/HttpServletRequest.getParameter:(Ljava/lang/String;)Ljava/lang/String;
   67:  invokevirtual   #5; //Method java/io/PrintStream.println:(Ljava/lang/String;)V
   70:  return

protected void doGet2(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)   throws javax.servlet.ServletException, java.io.IOException;
  Code:
   0:   aload_1
   1:   ldc     #3; //String locale
   3:   invokeinterface #4,  2; //InterfaceMethod javax/servlet/http/HttpServletRequest.getParameter:(Ljava/lang/String;)Ljava/lang/String;
   8:   astore_3
   9:   getstatic       #2; //Field java/lang/System.out:Ljava/io/PrintStream;
   12:  aload_3
   13:  invokevirtual   #5; //Method java/io/PrintStream.println:(Ljava/lang/String;)V
   16:  getstatic       #2; //Field java/lang/System.out:Ljava/io/PrintStream;
   19:  aload_3
   20:  invokevirtual   #5; //Method java/io/PrintStream.println:(Ljava/lang/String;)V
   23:  getstatic       #2; //Field java/lang/System.out:Ljava/io/PrintStream;
   26:  aload_3
   27:  invokevirtual   #5; //Method java/io/PrintStream.println:(Ljava/lang/String;)V
   30:  getstatic       #2; //Field java/lang/System.out:Ljava/io/PrintStream;
   33:  aload_3
   34:  invokevirtual   #5; //Method java/io/PrintStream.println:(Ljava/lang/String;)V
   37:  getstatic       #2; //Field java/lang/System.out:Ljava/io/PrintStream;
   40:  aload_3
   41:  invokevirtual   #5; //Method java/io/PrintStream.println:(Ljava/lang/String;)V
   44:  return
Wayne Young