Peter Lawrey at IT Days

I’ve just come back from a Java Performance Workshop held by Peter Lawrey at Cluj-Napoca IT Days.

Peter Lawrey is a well-known Java StackOverflow user and the creator of Java Chronicle open-source library.

Of Java and low latency

Little’s Law defines concurrency as:

$Throughput = \dfrac{Served Requests}{Latency}$

To increase throughput we can either:

• increase server resources (scaling vertically or horizontally)
• decrease latency (improve performance)

While enterprise applications are usually designed for scaling, trading systems focus on lowering latencies.

As surprising as it may sound, most trading systems, I’ve heard of, are actually written in Java. Java automatic memory management is a double-edged sword, since it trades simplicity for flexibility.

A low latency system worse nightmare is a stop-of-the-world process, like a garbage collector major collection. So in order to avoid such situations, you must go off-heap.

Basic time notions

Most web applications have to support different time-zones and properly handling time-zones is no way easy. To make matters worse, you have to make sure that timestamps are consistent across various programming languages (e.g. JavaScript on the front-end, Java in the middle-ware and MongoDB as the data repository). This post aims to explain the basic notions of absolute and relative time.

Epoch

An epoch is a an absolute time reference. Most programming languages (e.g Java, JavaScript, Python) use the Unix epoch (Midnight 1 January 1970) when expressing a given timestamp as the number of milliseconds elapsed since a fixed point-in-time reference.

Relative numerical timestamp

The relative numerical timestamp is expressed as the number of milliseconds elapsed since the epoch.

Time zone

The coordinated universal time (UTC) is the most common time standard. The UTC time zone (equivalent to GMT) represents the time reference all other time zones relate to (through a positive/negative offset).

UTC time zone is commonly referred as Zulu time (Z) or UTC+0. Japan time zone is UTC+9 and Honolulu time zone is UTC-10. At the time of Unix epoch (1 January 1970 00:00 UTC time zone) it was 1 January 1970 09:00 in Tokyo and 31 December 1969 14:00 in Honolulu.

ISO 8601

ISO 8601 is the most widespread date/time representation standard and it uses the following date/time formats:

Time zone Notation
UTC 1970-01-01T00:00:00.000+00:00
UTC Zulu time 1970-01-01T00:00:00.000Z
Tokio 1970-01-01T09:00:00.000+09:00
Honolulu 1969-12-31T14:00:00.000-10:00

Introduction

Application-level repeatable reads are suitable for preventing lost updates in web conversations. Enabling entity-level optimistic locking is fairly easy. You just have to mark one logical-clock property (usually an integer counter) with the JPA @Version annotation and Hibernate takes care of the rest.

The catch

Optimistic locking discards all incoming changes that are relative to an older entity version. But everything has a cost and optimistic locking makes no difference.

The optimistic concurrency control mechanism takes an all-or-nothing approach even for non-overlapping changes. If two concurrent transactions are changing distinct entity property subsets, then there’s no risk of losing updates.

Two concurrent updates, starting from the same entity version are always going to collide. It’s only the first update that’s going to succeed, the second one failing with an optimistic locking exception. This strict policy acts as if all changes are overlapping. For highly concurrent write scenarios, this single-version check strategy can lead to a large number of roll-backed updates.

Introduction

Hibernate provides an optimistic locking mechanism to prevent lost updates even for long-conversations. In conjunction with an entity storage, spanning over multiple user requests (extended persistence context or detached entities) Hibernate can guarantee application-level repeatable-reads.

The dirty checking mechanism detects entity state changes and increments the entity version. While basic property changes are always taken into consideration, Hibernate collections are more subtle in this regard.

Owned vs Inverse collections

In relational databases, two records are associated with a foreign key reference. In this relationship, the referenced record is the parent while the referencing row (the foreign key side) is the child. A non-null foreign key may only reference an existing parent record.

In the Object-oriented space, this association can be represented in both directions. We can have a many-to-one reference from a child to parent and the parent can also have a one-to-many children collection.

Because both sides could potentially control the database foreign key state, we must ensure that only one side is the owner of this association. Only the owning side state changes are propagated to the database. The non-owning side has been traditionally referred as the inverse side.

Next, I’ll describe the most common ways of modeling this association.