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

IdCompressor in the runtime #14340

Merged
merged 113 commits into from May 1, 2023

Conversation

justus-camp
Copy link
Contributor

@justus-camp justus-camp commented Feb 27, 2023

Description

This PR exists as a point of discussion for implementation details around integrating the IdCompressor into the runtime. This has been forked from #13398.

Details

What to Review

The IdCompressor has already been used in production in legacy SharedTree and is thoroughly tested. Anything in packages/runtime/container-runtime/src/id-compressor can be ignored for the purpose of this review as it's just being moved to the runtime folder.

Overview

The idea is to have a container runtime level IdCompressor that is shared across DDSs. DDS authors will be able to generate compressed Ids using the runtime-level compressor. Upon DDS op submission, the runtime checks the compressor's state to see if any compressed ops were generated that need to be sent. If there are IdAllocation ops, the runtime puts an IdAllocation op in front of the DDS's op.

Stashed Ops

The idea is to "resume" the IdCompressor that the stashed client was using by including the current compressor state in its contents. This is done using localOpMetadata until the container is closed using closeAndGetPendingLocalState. At this point, the localOpMetadata is copied into contents.stashedState so that the stashed state is stored for rehydrating the compressor. This state is deleted before sending the op over the wire for other compressors to synchronize.

Enablement and Compat

This feature is turned off by default and must be explicitly enabled. The feature gate is enableRuntimeIdCompressor. The idea here is to do the same thing we did with compression where we make breaking changes without them turning on until reaching proper saturation.

Exposure to DDS

The IdCompressor exists inside the container runtime but needs to be accessed by DDSs. I've added accessors to the IdCompressor from the container runtime down to the DataStoreRuntime level.

I've introduced two new interfaces to runtime-definitions: IdCompressorCore and IdCompressor. IdCompressorCore contains methods that shouldn't be exposed to a DDS author, but should be exposed at the container runtime level to manage the IdCompressor's state. Upon retrieving the IdCompressor, the DDS has access to all methods present in the IdCompressor interface.

Finalizing Id Ranges

IdRanges are included inside DataStoreOp's contents at the SharedObjectCore level inside of submitLocalMessage. It must be included in the op's contents so that ops that are resubmitted through replayPendingStates correctly resubmit the IdRange. If appended at a higher level, the IdRange would be lost on replay.

Summarization

The IdCompressor's state is added to the summary inside ContainerRuntime::addContainerStateToSummary. I've added it as a blob (should it be a tree?). The blob is fetched as part of the ContainerRuntime's constructor.

justus-camp and others added 30 commits December 14, 2022 00:16
@@ -1442,6 +1485,8 @@ export class ContainerRuntime
disableChunking,
disableAttachReorder: this.disableAttachReorder,
disablePartialFlush,
idCompressorEnabled: compressorEnabled ? true : undefined,
Copy link
Contributor

Choose a reason for hiding this comment

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

Isn't idCompressorEnabled: compressorEnabled enough? If it is explicitly set to false, you want false to be logged.

);
}
assert(
this.idCompressor !== undefined,
Copy link
Contributor

Choose a reason for hiding this comment

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

nit: Use this.idCompressorEnabled.

Comment on lines +1993 to +1994
assert(
this.idCompressor !== undefined,
Copy link
Contributor

Choose a reason for hiding this comment

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

nit: Use this.idCompressorEnabled.

@@ -139,6 +139,40 @@ describeNoCompat("Runtime IdCompressor", (getTestObjectProvider) => {
assert(getIdCompressor(map) === undefined);
});

it("can't enable compressor on an existing container", async () => {
Copy link
Contributor

Choose a reason for hiding this comment

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

I missed this in my last comment - You should another test that validates it cannot be disabled once enabled.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

"Ignores runtime option if container is created and IdCompressor has been previously enabled" is the test that covers this scenario

Copy link
Contributor

Choose a reason for hiding this comment

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

Nice! Maybe rename this test title for consistency with the other test.

Copy link
Contributor

@agarwal-navin agarwal-navin left a comment

Choose a reason for hiding this comment

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

Looks good! Note that I did not look at the id compressor specific changes. I looked at the runtime changes and tests only.

@justus-camp justus-camp merged commit fd88671 into microsoft:main May 1, 2023
30 checks passed
@ChumpChief
Copy link
Contributor

ChumpChief commented May 3, 2023

@fluid-example/bundle-size-tests: +100.09 KB

@justus-camp @agarwal-navin Has this bundle size increase been discussed? Seems likely to be a point of contention during integration.

Maybe consider whether the runtime performance gains of using the btree library are worth it vs. just a vanilla Map. Have we benchmarked to compare?

@agarwal-navin
Copy link
Contributor

Hmmm. I did not look at this, no. Maybe worth evaluating with @justus-camp and SharedTree folks.

@taylorsw04
Copy link
Contributor

Hmmm. I did not look at this, no. Maybe worth evaluating with @justus-camp and SharedTree folks.

@ChumpChief @agarwal-navin FYI I'm setting up some discussions to talk about need/mitigation here.

@anthony-murphy
Copy link
Contributor

anthony-murphy commented May 3, 2023

Hmmm. I did not look at this, no. Maybe worth evaluating with @justus-camp and SharedTree folks.

@ChumpChief @agarwal-navin FYI I'm setting up some discussions to talk about need/mitigation here.

@dannimad @taylorsw04 @ChumpChief @agarwal-navin this should be a blocker for the current minor release

justus-camp added a commit that referenced this pull request May 4, 2023
## Description

Moving the IdCompressor into the runtime (#14340 ) has resulted in a
large bundle size increase that we don't want consumers to take on while
the compressor isn't being used anywhere. By changing to dynamic
imports, only consumers who enable the compressor will have to pay
download cost.
justus-camp added a commit that referenced this pull request Jul 24, 2023
## Description

Follow-up from #14340 where I introduced
`createSummarizerWithTestConfig`, which should be the default usage
pattern. This removes the original `createSummarizer` and replaces it,
refactoring tests as necessary to use the new pattern.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area: dds: tree area: dds Issues related to distributed data structures area: runtime Runtime related issues area: tests Tests to add, test infrastructure improvements, etc base: main PRs targeted against main branch public api change Changes to a public API
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

7 participants