Question on Java IO Performance tuning
I am trying to optimize a web based application that does a lot of writing to the stream. The code is something like this ---
StringWriter stringWriter = new StringWriter(1024);
PrintWriter printWriter = new PrintWriter(stringWriter);
Then this printwriter is used to do a lot of write operations at several places like --
printWriter.write("set interface ethernet0 zone Trust");
I want to optimize the several write operations by wrapping the printwriter around a bufferedwriter. So i plan to change line1 and li开发者_JAVA技巧ne2 as below.Please let me know if the approach below is correct --
StringWriter stringWriter = new StringWriter(1024);
// go for bufferedwriter instead of printwriter.
BufferedWriter bufWriter = new BufferedWriter(stringWriter, 8*1024);
Also, I think that now I can replace the write method directly as in --
printWriter.write("set interface ethernet0 zone Trust");
replaced as
bufWriter.write("set interface ethernet0 zone Trust");
Please let me know if this is correct or do I need to use any of the overloaded methods of BufferedWriter to take full advantage of the BufferedWriter.
Thanks, Dev
Since StringWriter
writes into a string buffer (in memory) per definition, wrapping it into a BufferedWriter
should not have any effect in performance. (Due to the additional level of indirection, it may in fact make your code a bit slower - although this will may be most likely optimized away by the JIT compiler.)
The latter is useful in file I/O where one big write tends to be much faster than several small ones.
Why do you think you need to tune this piece of code? It may be worth going through the following
General guidelines about performance tuning
- Don't do it (are you sure you need it? Most of the time you actually don't).
- Don't do it yet (relevant classic quote: "Premature optimization is the root of all evil" by Donald Knuth).
- Don't optimize code which you believe is slow - measure the performance with a profiler to find the actual bottlenecks.
- Measure again after any change to verify that you really improved performance noticeably (case in point: it is easy to make "clever" changes which don't make any difference, or even deteriorate performance).
Adding the BufferedWriter only adds an additional copy operation for every char written. You should change the initial size of StringWriter instead, a larger initial size means less growing and less copying later.
The StringWriter itself contains a growing Buffer for character data, adding an additional buffer on top of it by using a BufferedWriter will not lead to a speed up. From the given code a larger initial size for the StringWriter object itself could help.
Do you really need to be using StringWriter? StringWriter is just a proxy for StringBuffer which synchronises on itself with each time append is called.
Have you considered using StringBuilder instead. It isn't synchronised (and therefore not thread safe), but should be faster -- especially if you are doing lots of short writes.
edit: The synchronisation issue is a doubly important as PrintWriter is also synchronised. Everytime you call print/write your code has to acquire and release two locks. I suspect this might be why you code is spending significant amounts of time in the write method.
edit: If you really must use PrintWriter then the following alternatives could work, on the caveat that the PrintWriter is only accessed by one thread -- otherwise it could cause a deadlock. To make this work well all writes must be performed in the SAME synchronized block, otherwise you will just hit the same problem -- eg entering and exiting lots of synchronized bits of code.
ByteArrayOutputStream out = new ByteArrayOutputStream(bufSize);
PrintWriter writer = new PrintWriter(out);
synchronized (writer) {
// do writes
}
writer.flush(); // very important or you may not see any output in 'out'
writer.close();
String output = out.toString();
If you don't have to use a PrintWriter then a StringWriter alone should suffice.
StringWriter writer = new StringWriter(bufSize);
synchronized(writer.getBuffer()) {
// do writes
}
writer.flush();
writer.close();
String output = writer.toString();
What was meant to be my initial suggestion:
StringBuilder builder = new StringBuilder();
// do APPENDS (instead of writes)
String output = builder.toString();
That you need to call append instead of write is why you would need to refactor your code.
I really doubt that BufferedWriter
will give any performance improvement here - both it and StringWriter
write straight to memory. If anything it will slow things (fractionally) down by adding a layer of indirection. Of course if you find differently please correct me. What makes you think this is a bottleneck?
精彩评论