Reputation: 131
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
Upvotes: 0
Views: 561
Reputation: 2895
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
Upvotes: 0
Reputation: 10665
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.
Upvotes: 2
Reputation: 20152
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.
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.
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.
Upvotes: 2