diff --git a/packages/runtime/container-runtime/src/opLifecycle/README.md b/packages/runtime/container-runtime/src/opLifecycle/README.md index c311df598a24..d39be741b3aa 100644 --- a/packages/runtime/container-runtime/src/opLifecycle/README.md +++ b/packages/runtime/container-runtime/src/opLifecycle/README.md @@ -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 @@ -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. @@ -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. ### Changes in op semantics @@ -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. @@ -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: @@ -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