Monday, December 5, 2011

The magic of conditional operator

Can you guess what is going to be the output of the following piece of code?
    Object obj = false ? new Long(1) : new Integer(1);
    System.out.println(obj.getClass());
The smart once can guess that it is going to be "class java.lang.Long", otherwise there won't be a question. Now can you answer why? To be honest, I was a surprised by such an outcome, but apparently, according to JLS that is correct behaviour. Here is quotation from "15.25 Conditional Operator ? :":

The type of a conditional expression is determined as follows:
  • If the second and third operands have the same type (which may be the null type), then that is the type of the conditional expression.
  • If one of the second and third operands is of type boolean and the type of the other is of type Boolean, then the type of the conditional expression is boolean.
  • If one of the second and third operands is of the null type and the type of the other is a reference type, then the type of the conditional expression is that reference type.
  • Otherwise, if the second and third operands have types that are convertible (§5.1.8) to numeric types, then there are several cases:
    • If one of the operands is of type byte or Byte and the other is of type short or Short, then the type of the conditional expression is short.
    • If one of the operands is of type T where T is byte, short, or char, and the other operand is a constant expression of type int whose value is representable in type T, then the type of the conditional expression is T.
    • If one of the operands is of type Byte and the other operand is a constant expression of type int whose value is representable in type byte, then the type of the conditional expression is byte.
    • If one of the operands is of type Short and the other operand is a constant expression of type int whose value is representable in type short, then the type of the conditional expression is short.
    • If one of the operands is of type; Character and the other operand is a constant expression of type int whose value is representable in type char, then the type of the conditional expression is char.
    • Otherwise, binary numeric promotion (§5.6.2) is applied to the operand types, and the type of the conditional expression is the promoted type of the second and third operands. Note that binary numeric promotion performs unboxing conversion (§5.1.8) and value set conversion (§5.1.13).
  • Otherwise, the second and third operands are of types S1 and S2 respectively. Let T1 be the type that results from applying boxing conversion to S1, and let T2 be the type that results from applying boxing conversion to S2. The type of the conditional expression is the result of applying capture conversion (§5.1.10) to lub(T1, T2) (§15.12.2.7).

In the other words, it says that if second and third operands are convertible to primitive numeric types, then the result type is based on numeric promotion of converted values. Here how it looks after applying these rules:
Object obj = Long.valueOf(false ? (new Long(1L)).longValue() : (new Integer(1)).intValue());
My opinion, it all looks like a magic, and at the end, that's the price Java paid for autoboxing. Well world is not perfect and that's it's beauty, isn't it? :)

Wednesday, November 9, 2011

Java file flushing performance

There are many situations when it is required to ensure that data was written to the disk and write is also required to be fast. The most most common where it has to happen are databases, journalling, etc. Also, it is often required to update some random position in a file. I specifically what to place emphasis on random access here, as far as the rest will cover just cases where it is supported, i.e. I'm not going to mention OutputStream.flush() & related topics. Just haven't tried it, as far as that wasn't my case at the moment.

There are several way of flushing the data to disk in java. These options can be quite different in the way they implemented internally and in their performance. Here is the list of existing things you can do:
  • FileChannel.force()
  • 'rws' or 'rwd' mode of RandomAccessFile, which 'works much like the force(boolean) method of the FileChannel class' (from javadoc).
  • MappedbyteBuffer.force()
  • RandomAccessFile.getFD().sync()
  • any close() method. Here I mean seek and close stream each time when access is required. Doing tests, I actually didn't seek, as far was updating data with zero offset.
Surprisingly (the only unsurprising exception is close()) all these methods gives very different performance and it varies almost randomly on different OSes and file systems. Worth noticing that hardware can also put it's correction on the performance of any of these methods. I have also a strong feeling that performance may vary even with minor change in OS or JVM version number. Here is the table with time it takes to flush 8bytes (keep in mind, that the real amount of flushed data depends on the size of caches and going to be much more that 8byes), just to give a flavour of how different is that:

RandomAccessFile.
getFD().sync()
RandomAccessFile, rwd mode MappedbyteBuffer.force()FileChannel.force()
Windows 0.2818ms0.0125ms 0.007ms 0.139ms
Linux 0.5354ms 0.5144ms 0.4663ms 0.0093ms

Please, do not treat these numbers as any relevant result. They are here just to give an example how these things can vary.

So, what the conclusion? Conclusion is that if you would need to write high-performance application which does lots of IO, you really need to test different approached on different OSes, on different file systems and, preferably  on different JVMs. Do not expect something to be fast on Linux (Solaris, AIX, etc) production box, when it is fast on your Windows (Linux, etc) workstation and vice versa. As can be seen, the difference can be in orders of magnitude.

Wednesday, July 20, 2011

The most complete list of -XX options for Java JVM

There was a wonderful page with that list (http://www.md.pp.ru/~eu/jdk6options.html), but it seems it's gone now and not available any more. Luckily there is http://web.archive.org which allows to make time flowing backwards and recover things which have passed away long time back. So, I have just get that page out of grave and copy/pasted here to return that bit of information back to life. Also I'm constantly doing updates to the original list, so by now it should be longer than it was initially.

Tuesday, July 12, 2011

Integration of TeamCity 6.x and Fitnesse

Team city is wonderful CI and build management platform, which combines great capabilities with really simple configuration. I seriously love it for the way it is designed, configured and managed and would recommend it to anybody who cares about quality and wants to have fast feedback on build/test/integration problems. FitNess is “The fully integrated standalone wiki, and acceptance testing framework”, which I, personally, do not like, but testers (at least ones I know) say it is good. I still do not believe them, but have to live with it :)

Sunday, July 3, 2011

EhCache replication: RMI vs JGroups.

Recently, I was working on one product which required replicated caching. Caching provider was already decided - EhCache, and the remained was a question about transport. Which one is the best option? By the best option here I mean just the one which has better performance. The performance measurement was done just between two of available transports - JGroups and RMI, others were not considered, sorry.

Saturday, January 15, 2011

jakarta regexp vs java.util.regex

Have never really been thinking about which library to use for regular expression, it always was java.util.regex by default. But I found that some people prefer to use Jakarta Regexp, and usually there is not clear reason for that choice. So, I decided to spent some time trying to find out what is better and probably write a couple of tests. After some time spent in the Internet looking for the examples of tests, it appeared that there was a good guy already who have done all that work. Here is the link to the page with results of his investigation:

http://tusker.org/regex/regex_benchmark.html

The conclusion is that Jakarta Regexp doesn't look good at all. Also you may notice that there are some other libraries who are doing regexps and some have very impressive performance and seems like worth trying.

UPDATE 09/2012: Thank's for comments from Cd MaN, there is newer update of that benchmark: http://hype-free.blogspot.ro/2008/12/big-java-regex-shoutout.html