Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update Documentation in OpLifecycle #23636

Merged
merged 3 commits into from
Jan 29, 2025
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
77 changes: 43 additions & 34 deletions packages/runtime/container-runtime/src/opLifecycle/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,21 +2,23 @@

## Table of contents

- [Configs and feature gates for solving the 1MB limit.](#configs-and-feature-gates-for-solving-the-1mb-limit)
- [Table of contents](#table-of-contents)
- [Introduction](#introduction)
- [How batching works](#how-batching-works)
- [Compression](#compression)
- [Grouped batching](#grouped-batching)
- [Changes in op semantics](#changes-in-op-semantics)
- [Chunking for compression](#chunking-for-compression)
- [Configuration](#configuration)
- [Note about performance and latency](#note-about-performance-and-latency)
- [How it works](#how-it-works)
- [How it works (Grouped Batching disabled)](#how-it-works-grouped-batching-disabled)
- [How the overall op flow works](#how-the-overall-op-flow-works)
- [Outbound](#outbound)
- [Inbound](#inbound)
- [Configs and feature gates for solving the 1MB limit.](#configs-and-feature-gates-for-solving-the-1mb-limit)
- [Table of contents](#table-of-contents)
- [Introduction](#introduction)
- [How batching works](#how-batching-works)
- [Grouped batching](#grouped-batching)
- [Changes in op semantics](#changes-in-op-semantics)
- [Compression](#compression)
- [Only single-message batches are compressed](#only-single-message-batches-are-compressed)
- [Chunking for compression](#chunking-for-compression)
- [Configuration](#configuration)
- [Note about performance and latency](#note-about-performance-and-latency)
- [How it works](#how-it-works)
- [Legacy behavior - How it used to work (Compression+Chunking without Grouped Batching)](#legacy-behavior---how-it-used-to-work-compressionchunking-without-grouped-batching)
- [IMPORTANT - As of 2.20.0, we no longer compress ungrouped batches, but we do need to read such ops - read on to learn what these legacy ops look like](#important---as-of-2200-we-no-longer-compress-ungrouped-batches-but-we-do-need-to-read-such-ops---read-on-to-learn-what-these-legacy-ops-look-like)
- [How the overall op flow works](#how-the-overall-op-flow-works)
- [Outbound](#outbound)
- [Inbound](#inbound)

## Introduction

Expand Down Expand Up @@ -56,20 +58,6 @@ What this means is that `FlushMode.Immediate` will send each op in its own paylo

As `FlushMode.TurnBased` accumulates ops, it is the most vulnerable to run into the 1MB socket limit.

## Compression

**Compression targets payloads which exceed the max batch size and it is enabled by default.**. The `IContainerRuntimeOptions.compressionOptions` property, of type `ICompressionRuntimeOptions` is the configuration governing how compression works.

`ICompressionRuntimeOptions` has two properties:

- `minimumBatchSizeInBytes` – the minimum size of the batch for which compression should kick in. If the payload is too small, compression may not yield too many benefits. To target the original 1MB issue, a good value here would be to match the default maxBatchSizeInBytes (972800), however, experimentally, a good lower value could be at around 614400 bytes. Setting this value to `Number.POSITIVE_INFINITY` will disable compression.
- `compressionAlgorithm` – currently, only `lz4` is supported.

Compression is relevant for both `FlushMode.TurnBased` and `FlushMode.Immediate` as it only targets the contents of the ops and not the number of ops in a batch. Compression is opaque to the server and implementations of the Fluid protocol do not need to alter their behavior to support this client feature.

Compressing a batch yields a batch with the same number of messages. It compresses all the content, shifting the compressed payload into the first op,
leaving the rest of the batch's messages as empty placeholders to reserve sequence numbers for the compressed messages.

## Grouped batching

With Grouped Batching enabled (it's on by default), all batch messages are combined under a single "grouped" message _before compression_. Upon receiving this new "grouped" message, the batch messages will be extracted, and they each will be given the same sequence number - that of the parent "grouped" message.
Expand All @@ -78,9 +66,7 @@ The purpose for enabling grouped batching before compression is to eliminate the

Grouped batching is only relevant for `FlushMode.TurnBased`, since `OpGroupingManagerConfig.opCountThreshold` defaults to 2. Grouped batching is opaque to the server and implementations of the Fluid protocol do not need to alter their behavior to support this client feature.

Grouped Batching can be disabled by setting `IContainerRuntimeOptions.enableGroupedBatching` to `false`.

See [below](#how-grouped-batching-works) for an example.
See [below](#how-it-works) for an example.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this link work?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It didn't before so I fixed it.


### Changes in op semantics

Expand All @@ -92,6 +78,27 @@ Grouped Batching changed a couple of expectations around message structure and r
- All ops in a batch must also have the same reference sequence number to ensure eventualy consistency of the model. The runtime will "rebase" ops in a batch with different ref sequence number to satisfy that requirement.
- What causes ops in a single JS turn (and thus in a batch) to have different reference sequence number? "Op reentrancy", where changes are made to a DDS inside a DDS 'onChanged' event handler.

## Compression

**Compression targets payloads which exceed the max batch size and it is enabled by default.**. The `IContainerRuntimeOptions.compressionOptions` property, of type `ICompressionRuntimeOptions` is the configuration governing how compression works.

`ICompressionRuntimeOptions` has two properties:

- `minimumBatchSizeInBytes` – the minimum size of the batch for which compression should kick in. If the payload is too small, compression may not yield too many benefits. To target the original 1MB issue, a good value here would be to match the default maxBatchSizeInBytes (972800), however, experimentally, a good lower value could be at around 614400 bytes. Setting this value to `Number.POSITIVE_INFINITY` will disable compression.
- `compressionAlgorithm` – currently, only `lz4` is supported.

Compression is relevant for both `FlushMode.TurnBased` and `FlushMode.Immediate` as it only targets the contents of the ops and not the number of ops in a batch. Compression is opaque to the server and implementations of the Fluid protocol do not need to alter their behavior to support this client feature.

### Only single-message batches are compressed

The batch to compress has to have only one message and it yields a batch with a single message. It compresses all the content, replacing the op's original contents with the compressed payload and the appropriate metadata to indicate it's compressed.

Compression is only enabled if Grouped Batching is enabled.

Legacy compressed batches could contain multiple messages, compressing all the content and shifting the compressed payload into the first op, leaving the rest of the batch's messages as empty placeholders to reserve sequence numbers for the compressed messages.

While it remains possible to read compressed batches with empty ops, the system will no longer create said type of batches.

## Chunking for compression

**Op chunking for compression targets payloads which exceed the max batch size after compression.** So, only payloads which are already compressed. By default, the feature is enabled.
Expand Down Expand Up @@ -200,7 +207,9 @@ Ungrouped batch:
+-----------------+-----------------+-----------------+-----------------+-----------------+
```

## How it works (Grouped Batching disabled)
## Legacy behavior - How it used to work (Compression+Chunking without Grouped Batching)

### IMPORTANT - As of 2.20.0, we no longer compress ungrouped batches, but we do need to read such ops - read on to learn what these legacy ops look like

If we have a batch with a size larger than the configured minimum required for compression (in the example let’s say it’s 850 bytes), as following:

Expand Down Expand Up @@ -311,7 +320,7 @@ stateDiagram-v2
groupBatch --> if_compression
flushInternal --> if_compression
if_compression --> post
if_compression --> compress: if compression is enabled
if_compression --> compress: if compression and grouped batching are enabled
compress --> post
compress --> opSplitter.split: if the compressed payload is larger than the chunk size
opSplitter.split --> post
Expand Down
Loading