Posts

Demystifying Java Object Sizes: Compact Headers, Compressed Oops, and Beyond

Introduction Measuring an object’s size in Java is not straightforward. The platform encourages you to consider references and abstractions rather than raw memory usage. Still, understanding how objects fit into memory can yield significant benefits, especially for high-performance, low-latency systems. Over time, the JVM has introduced optimisations like Compressed Ordinary Object Pointers (Compressed Oops) and, more recently, Compact Object Headers. Each of these can influence how large or small your objects appear. Understanding these factors helps you reason about memory usage more concretely. Measuring Object Sizes In principle, you can estimate an object’s size by creating instances and observing changes in the JVM’s free memory. However, you must neutralise certain factors to get consistent results. For example, turning off TLAB allocation ( -XX:-UseTLAB ) makes memory usage more directly observable. Repeated measurements and median calculations can reduce the im...

Novel Uses of Core Java for Low-Latency and High-Performance Systems

Standard Java libraries and idioms may only sometimes suffice in high-performance and low-latency Java systems. This article explores unconventional yet practical techniques that push Core Java to its limits, focusing on performance, diagnostics, and determinism. Drawing on experiences from building ultra-low-latency libraries and infrastructure, we will highlight patterns such as capturing stack traces without exceptions, system-wide unique timestamps, "trivially copyable" data types, zero-garbage strategies, and more. We will also discuss lessons from applying these approaches in production environments, where nanosecond-level considerations are the norm. This is taken from the transcript for Novel Uses of Core Java for Low-Latency and High-Performance Systems Moderated by Melissa McKay . Introduction Developers often rely on standard Java idioms— throwable hierarchies, BigDecimal for financial calculations, thread-local resources, or off-the-shelf message...

Trivially Copyable Objects in Java

TL;DR Problem: Java’s standard serialisation can be slow due to scattered object fields and reflection-based overhead. Approach: Emulate C++-style trivially copyable objects by restricting fields to primitives, enabling bulk memory copies. Result: Near C++-like serialisation performance, dramatically reducing latency and improving throughput. Trade-offs: Requires careful design, limited flexibility, and testing for JVM compatibility. Outcome: Low-latency systems with high performance, suitable for financial data feeds, real-time analytics, and other latency-sensitive domains. Introduction For low-latency systems, every microsecond has tangible business impact. In high-frequency trading, real-time analytics, and similarly time-sensitive workloads, even minor inefficiencies in serialisation and deserialisation can degrade throughput and responsiveness. The seemingly mundane act of converting objects into bytes and back often becomes a performance bottleneck. Thi...

Efficient Distributed Unique Timestamp Identifier Generation

Distributed unique timestamp identifiers, generated in sub-microsecond time, enable systems to assign globally unique, human-readable 64-bit values at extremely high throughput. This approach helps align event ordering across hosts and simplifies debugging in complex, time-sensitive, and latency-critical environments. Introduction In a world of horizontally scaled microservices, ensuring that each event or message receives a unique identifier across multiple machines can be challenging. Traditional approaches often rely on UUIDs, which—while easy to use—lack intuitive readability and can be relatively expensive to generate in ultra-low-latency scenarios. Our solution builds upon nanosecond-resolution timestamps combined with a host identifier embedded directly into the lower-order digits of the timestamp. This technique, inspired by previous work on system-wide unique nanosecond timestamps, creates identifiers that are compact, human-interpretable, and extremely fast to ...

A Java Conversion Puzzler: Understanding Implicit Casting and Overflow

This article explores a subtle Java conversion puzzle that challenges assumptions about how arithmetic operations, implicit casting, and floating-point conversions interact. Inspired by complexities often encountered in low-latency and high-performance environments, it demonstrates why a keen understanding of Java’s type system is essential for building reliable and efficient applications. Introduction The following example demonstrates a scenario where an innocuous-looking arithmetic operation leads to a surprising result. While such questions are rare and arguably impractical, they highlight subtle behaviours that can affect correctness and performance, especially in critical systems like high-frequency trading platforms or complex data-processing pipelines. The Problem: A Surprising Print Statement Consider the following code: int i = Integer.MAX_VALUE; i += 0.0f; int j = i; System.out.println(j == Integer.MAX_VALUE); // true At first glance, one might assume that adding...

Why Does Math.round(0.49999999999999994) Round to 1?

1. Defining the Problem In many numerical computations, one would reasonably expect that rounding 0.499999999999999917 should yield 0 , since it appears to be slightly less than 0.5 . Yet, in Java 6, calling Math.round() on this value returns 1 , a result that may initially seem baffling. This seemingly minor discrepancy stems from the interplay of binary floating-point representation, rounding modes, and the particular internal implementation details of Math.round() in earlier Java releases. For professionals in performance-sensitive environments—such as those working in financial technology or high-precision scientific applications—understanding these subtleties is more than just an academic exercise. Even tiny rounding differences can influence trading algorithms, pricing models, or simulations. Moreover, developers and enthusiasts who appreciate the low-level mechanics behind Java’s numeric types will find valuable insights into how these internal workings affect everyday pro...