Posts

Why double Still Outperforms BigDecimal: A Decade-Long Performance Comparison

Overview Many developers consider BigDecimal the go-to solution for handling money in Java. They often claim that replacing double with BigDecimal has fixed one or more bugs in their applications. However, I find this reasoning unconvincing. The issue may lie not with double but rather with how it was handled. Additionally, BigDecimal introduces significant overhead that may not justify its use. When asked to improve the performance of a financial application, I know that if BigDecimal is involved, it will eventually need to be removed. While it may not be the largest performance bottleneck initially, as we optimise the system, BigDecimal often becomes one of the main culprits. BigDecimal is Not an Improvement BigDecimal comes with several drawbacks. Here are some of its key issues: It has an unnatural syntax. The API is verbose and can be cumbersome to use. It uses more memory. BigDecimal objects consume more memory compared to primitive types. It ...

Incomparable Puzzles in Java

Here are a few puzzles for you to solve in Java. The source is available here: UncomparablePuzzles.java . Puzzle 1: Comparing long and double Try running the following code to reproduce the output below. See if you can work out why these results occur: long a = ( 1L << 54 ) + 1 ; double b = a ; System . out . println ( "b == a is " + ( b == a )); System . out . println ( "(long) b < a is " + (( long ) b < a )); When executed, it produces: b == a is true (long) b < a is true Analysis This puzzle highlights the precision limitations when converting between long and double . Precision Loss During Conversion The long value a is (1L << 54) + 1 , which is 18014398509481985 . When cast to double , b becomes 18014398509481984.0 . Due to double 's 53-bit mantissa, it cannot accurately represent every long value beyond this range, resulting in precision loss. Equality Comparison ( b ...

Ten Java Myths and Misconceptions

Advanced Java Questions These questions delve into Java’s more intricate behaviours and are often too advanced for typical interviews, as they might be discouraging for candidates. However, they are excellent for deepening your understanding of Java’s core workings in your own time. Myth 1: System.exit(0) Prevents finally Block Execution Consider the following code: System . setSecurityManager ( new SecurityManager () { @Override public void checkExit ( int status ) { throw new ThreadDeath (); } }); try { System . exit ( 0 ); } finally { System . out . println ( "In the finally block" ); } This code will output: In the finally block Explanation : The System.exit(0) call triggers the checkExit method in the custom SecurityManager . By throwing a ThreadDeath exception instead of terminating, the finally block is allowed to execute, explaining the "In the finally block" output. Since Th...

Java Arrays, Wat!

Java arrays are a fundamental component of the language, yet they can exhibit behaviours that surprise even seasoned developers. This article delves into some of these quirks, providing clarity and practical insights for Java developers. Is it an Array or Not? Consider the following declaration: Serializable [] array2 = new Serializable [ 9 ]; Serializable array = array ; Cloneable [][] arrayA = new Serializable [ 9 ][]; Cloneable [] arrayB = arrayA ; Cloneable arrayC = arrayA ; At first glance, one might question whether array is an array or a scalar. In reality, array is a scalar reference that points to an array. This behaviour is consistent across Java’s type system. For instance: Object o = new Object [ 9 ]; Here, you can assign an array to an Object variable because arrays are also objects in Java. Additionally, arrays are Serializable and Cloneable , so they can be assigned to a Serializable or Cloneable reference...

Some Common Java Gotchas and How to Avoid Them

Advanced Java Questions These questions delve into Java’s more intricate behaviours and are often too advanced for typical interviews, as they might be discouraging for candidates. However, they are excellent for deepening your understanding of Java’s core workings in your own time. Myth 1: System.exit(0) Prevents finally Block Execution Consider the following code: System . setSecurityManager ( new SecurityManager () { @Override public void checkExit ( int status ) { throw new ThreadDeath (); } }); try { System . exit ( 0 ); } finally { System . out . println ( "In the finally block" ); } This code will output: In the finally block Explanation : The System.exit(0) call triggers the checkExit method in the custom SecurityManager . By throwing a ThreadDeath exception instead of terminating, the finally block is allowed to execute, explaining the "In the finally block" output. Since Th...

Java is Very Fast, If You Don’t Create Many Objects

Image
  You still have to watch how many objects you create. This article looks at a benchmark passing events over TCP/IP at 4 billion events per minute using the net.openhft.chronicle.wire.channel package in Chronicle Wire and why we still avoid object allocations..  One of the key optimisations is creating almost no garbage. Allocation is a very cheap operation and collection of very short-lived objects is also very cheap. Does this really make a difference? What difference does one small object per event (44 bytes) make to the performance in a throughput test where GC pauses are amortised? While allocation is as efficient as possible, it doesn’t avoid the memory pressure on the L1/L2 caches of your CPUs and when many cores are busy, they are contending for memory in the shared L3 cache.  Results Benchmark on a Ryzen 5950X with Ubuntu 22.10. JVM Vendor, Version No objects Throughput, Average Latency* One object per event Throughput, Average Latency* Azul Zulu 1.8.0_322 60.6 ...