Chapter 6. Recycling Regardless of continuous improvements in

October 30, 2006 on 7:28 am | In Java | No Comments

Optimization 36: Object Recycling In general, when faced with an expensive computation, my first question is not How can I speed up this computation?, but rather Can I modify my design to get rid of this computation altogether? It is better to avoid a difficult situation in the first place rather than to find a clever way to get out. The same applies to object creation and garbage collection. It is preferred to restrict the proliferation of objects in Java code rather than to rely on the latest and greatest improvements in the garbage-collection subsystem. One way to limit the creation of new objects is to recycle old ones. Suppose you have a servlet that uses a Vector object in its response generation. Since a servlet is intended to serve repeated requests in its lifetime, you must decide what to do with this Vector object as it goes from one request to the next. You have a couple options: One, you could create a new Vector object for every request. Old Vector objects used by earlier requests are going to be garbage collected at some later point. The second option is to make it a member of the servlet object and recycle it from one invocation to the next. At the end of one request you reset the Vector member and reuse it for the next request. Of course, reseting an object often replicates much of the constructor code, but it avoids memory allocation and therefore should always be faster than new object construction. Consequently, recycling an object is the preferred way to go. It is faster and it reduces the memory footprint, a double bonus. Reduction in memory footprint could help application speed by increasing the effectiveness of the processor cache [BM99]. To quantify the performance win, we tested one million iterations of a loop in which a new Vector object was created every time: String s = “HelloWorld”; String p = null; long start = System.currentTimeMillis(); // <+++ Start timing for (int i = 0; i < n; i++) { Vector v = new Vector(); v.addElement(s); v.addElement(s); v.addElement(s); p = (String) v.elementAt(0); } long stop = System.currentTimeMillis(); // <+++ Stop timing We compared it to a second version that recycles the same Vector object from one iteration to the next: Vector v = new Vector(); long start = System.currentTimeMillis(); // <+++ Start timing for (int i = 0; i < n; i++) { v.clear(); // Reset the Vector to an initial state v.addElement(s); v.addElement(s); v.addElement(s); p = (String) v.elementAt(0); } Page 137
Note: If you are looking for cheapest and affordable webspace to host and run your servlet application check Astra servlet hosting services

Chapter 6. Recycling Regardless of continuous improvements in

October 30, 2006 on 7:28 am | In Java | No Comments

Chapter 6. Recycling Regardless of continuous improvements in memory management speed, allocating and eventually discarding objects (via garbage collection) will always impose a nontrivial performance cost on Java programs. Moreover, object creation itself imposes an additional cost of properly setting the initial state of the constructed object via a constructor invocation. Object construction triggers the following steps [LY97]: . Sufficient memory is allocated to hold all instance variables (object members) as well as those of each superclass. . All instance variables of this class and those of each superclass are initialized to their default values (numeric variables to 0, boolean to false, reference types to null.) . Proper values are assigned to the constructor arguments. . If the constructor starts with an explicit invocation of another constructor of the same class (using this), then that constructor is invoked after evaluation of its arguments. . Otherwise, implicitly or explicitly, the superclass constructor (super) is invoked after evaluation of its arguments, if any. . Instance variable initializers are executed for this class as they appear in the source code. . The rest of the constructor body is executed. As you can tell, object creation can get expensive very quickly. The cost is proportional to the number of instance variables, the depth of the inheritance chain for the constructed class instance itself, as well as to the complexity of any member object references that are initialized to anything other than null. The least expensive objects are those that are never constructed. This chapter presents a few optimizations that try to circumvent the whole issue of object construction and destruction by recycling old ones. Page 136
Note: If you are looking for cheapest and affordable webspace to host and run your servlet application check Astra servlet hosting services

Page 134

October 30, 2006 on 6:01 am | In Java | No Comments

Key Points . Output buffering is one of the two big issues with stream output performance. Buffering spreads the fixed cost of an I/O call over a large number of bytes and reduces the cost per byte. There’s no need to write any buffering code yourself. The I/O library is already equipped with buffered streams. Just use them. . Buffering efficiency is sensitive to the size of the underlying buffer. The default sizes seem to be okay. If you choose to conserve memory and lower the size of the buffer, remember that as the size of the buffer decreases, performance gains slowly evaporate. . Frequent, periodic flushes may undermine the buffering mechanism. Pick your flushing spots carefully. . If you turn on the autoFlush feature of the PrintWriter, you can forget about efficiency. . Conversion of Unicode characters to bytes is expensive. Consequently, it is faster to send a byte array down a stream than a Unicode String through a writer. . Failure to buffer input data will result in physical reads of a single byte at a time. It could degrade performance by an order of magnitude. This loss is worse than a failure to buffer output because your typical output calls will attempt to write more than a single byte. . The DataInputStream will outperform input readers when ASCII streams are being read. The DataInputStream performs a proper byte-to-Unicode conversion for ASCII streams only. This is the classic tradeoff between speed and flexibility. . Not surprisingly, reading and writing binary data is vastly superior (in performance) to reading and writing Unicode characters. Page 135

Hint: This post is supported by Gama hrvatski web hosting services

Page 134

October 30, 2006 on 6:01 am | In Java | No Comments

Page 134

Hint: This post is supported by Gama hrvatski web hosting services

Page 132

October 30, 2006 on 4:34 am | In Java | No Comments

Page 133

Hint: This post is supported by Gama web hosting hrvatska services

Page 132

October 30, 2006 on 4:34 am | In Java | No Comments

Page 132

Hint: This post is supported by Gama web hosting hrvatska services

Optimization 35: Binary I/O Up to this point

October 30, 2006 on 2:30 am | In Java | No Comments

Page 131
Note: If you are looking for cheap and inexpensive provider to host and run your tomcat application check Actions tomcat hosting services

Optimization 35: Binary I/O Up to this point

October 30, 2006 on 2:30 am | In Java | No Comments

Optimization 35: Binary I/O Up to this point we have focused all our attention on the performance aspects of producing and consuming human-readable I/O. Towards that goal we have stripped away all other computations that might have consumed our precious CPU cycles and clouded the I/O performance picture we were trying to highlight. For example, we constructed the String representation of a Trade object right in the Trade constructor so as to take this computation outside the performance-critical path of our specific test program. There are two major drawbacks to that approach. . First, this approach is not very realistic. When we read a Trade String representation from the input file, we never bothered to reconstruct the underlying Trade object. We simply tossed away the line we read not a very realistic solution. . Second, we have committed a performance sin by computing the Trade String representation inside its constructors. This is a very bad idea. An object, in general, may be used in many different ways without ever needing to call its toString() method. If we call such an expensive method in the object constructor, we are penalizing all users of the class, whether they need this computation or not. One of the points we try to stress in this book is that you need to defer costly computations to the point at which you actually need them (Optimization 12). We have violated this principle in order to drive the I/O performance story. So let’s put the discussion back on more realistic grounds. We will modify the Trade class by taking the String computation out of the constructors and into toString() where it belongs: class Trade implements Serializable { String date; boolean buy; String symbol; int numShares; float price; public Trade (String d, boolean b, int n, String s, float p) { symbol = s; numShares = n; buy = b; date = d; price = p; } public Trade (String tr) { StringTokenizer st = new StringTokenizer(tr, ” “); date = st.nextToken(); if (”Buy”.equals(st.nextToken())) { buy = true; } else { buy = false; } numShares = Integer.parseInt(st.nextToken()); Page 130
Note: If you are looking for cheap and inexpensive provider to host and run your tomcat application check Actions tomcat hosting services

Optimization 34: Byte-to-Char Conversions Previously, we saw the

October 30, 2006 on 1:19 am | In Java | No Comments

Optimization 34: Byte-to-Char Conversions Previously, we saw the way converting Unicode characters to a byte stream could take a toll on performance. A similar issue exists in the reverse direction if a byte stream needs to be converted into Unicode characters. We have already encountered this issue in Optimization 4. There we recommended the use of a deprecated method to do the conversion when ASCII strings are involved. The politically correct way to convert a byte stream into a Unicode stream is by use of the FileReader, as in BufferedReader fr = new BufferedReader( new FileReader(”filename”)); String line = fr.readLine(); We tried this approach on our test loop by replacing the FileInputStream with a FileReader: BufferedReader fr = new BufferedReader( new FileReader(”stock.dat”)); String line = null; long start = System.currentTimeMillis(); // <+++ Start timingwhile ((line = fr.readLine()) != null) { // 100,000 iterations} long stop = System.currentTimeMillis();// <+++ Stop timing Execution time using the FileReader increased to 5.3 seconds. Recall from Optimization 33 that the very same code using a DataInputStream took only 4.7 seconds. See Figure 5.6. Figure 5.6. An InputStream is faster than a Reader The difference is due to the fact that the DataInputStream readLine() method is "cheating" by blindly casting a byte into a Unicode char. This step works only if the byte represents an ASCII character, but it is fast. If you know that your input byte stream is an ASCII stream, there's no harm Page 128
Note: If you are looking for cheap and reliable provider to host and run your servlet application check Vision servlet hosting services

Optimization 34: Byte-to-Char Conversions Previously, we saw the

October 30, 2006 on 1:19 am | In Java | No Comments

Page 129
Note: If you are looking for cheap and reliable provider to host and run your servlet application check Vision servlet hosting services

« Previous PageNext Page »