Hybrid Logical Clock
A hybrid logical clock implementation in Dart based on the paper Logical Physical Clocks and Consistent Snapshots in Globally Distributed Databases.
This library provides a Hybrid Logical Clock (HLC) implementation that combines the benefits of logical clocks and physical clocks:
- Captures causality like logical clocks (e hb f => l.e < l.f)
- Maintains closeness to physical time (l.e is close to pt.e)
- Fits in 64 bits: 48 bits of milliseconds since the Unix epoch, 16 bits of counter
- Works in peer-to-peer architectures without a central server
If e happened before f, then e < f. The reverse does not hold: e < f also when e and f are concurrent, so the order alone cannot detect concurrency.
Features
- Local event handling
- Message exchange between peers
- Total order that respects causality (
compareTo,<,>,max,min) - Serialization to/from 64-bit integers (
toInt64/fromInt64) - Compact 8-byte big-endian binary representation (
toUint8List/fromUint8List) — usable as a building block inside larger binary frames (e.g.OperationIdincrdt_lf) - A full counter moves
lforward by 1 ms, so the 8-byte form never wraps - Zero dependencies
- Drift detection
- Mutable and immutable methods for every needed operation
Getting Started
Add this to your package's pubspec.yaml file:
dependencies:
hlc_dart:
Usage
Basic Usage
import 'package:hlc_dart/hlc_dart.dart';
// Create a new HLC initialized to the current time
final clock = HybridLogicalClock.now();
// Handle a local event
clock.localEvent(DateTime.now().millisecondsSinceEpoch);
// Handle receiving a message from another peer
final receivedClock = HybridLogicalClock.now();
clock.receiveEvent(DateTime.now().millisecondsSinceEpoch, receivedClock);
// Check causality
print(clock.happenedBefore(receivedClock));
print(clock.happenedAfter(receivedClock));
print(clock.isConcurrentWith(receivedClock));
print(clock >= receivedClock);
print(clock < receivedClock);
// Serialize/deserialize as a 64-bit integer
final serialized = clock.toInt64();
final deserialized = HybridLogicalClock.fromInt64(serialized);
// Or as a compact 8-byte big-endian buffer (useful when embedding an HLC
// inside a larger binary frame).
final bytes = clock.toUint8List();
final fromBytes = HybridLogicalClock.fromUint8List(bytes);
Complete Example
Benchmarks
The latest results are here.
To run the benchmarks yourself, run from the repository root:
melos run benchmark_dart
Roadmap
A roadmap is available in the project page. The roadmap provides a high-level overview of the project's goals and the current status of the project.
Apps
- greyhound_markdown — Real-time collaborative markdown editor built on crdt_lf
Packages
Other bricks of the crdt "system" are: