-
Notifications
You must be signed in to change notification settings - Fork 1.4k
Refactor Node IDs for taskhost to use record struct #12830
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
base: main
Are you sure you want to change the base?
Conversation
|
Hello @@copilot, I noticed that you’re changing an .swr file or any file under src/Package/MSBuild.VSSetup.. Please make sure to validate this change by an experimental VS insertion. This is accomplished by pushing to an exp/* branch, which requires write permissions to this repo. |
- Created TaskHostNodeKey record struct combining HandshakeOptions and NodeId - Updated NodeProviderOutOfProcTaskHost to use TaskHostNodeKey as dictionary keys - Added reverse mapping from communication nodeId to TaskHostNodeKey for packet routing - Updated TaskHostTask to use TaskHostNodeKey instead of bit-packed int - Removed 256-node limitation for multithreaded builds - Added unit tests for TaskHostNodeKey Co-authored-by: JanProvaznik <[email protected]>
…of hash Address code review feedback: Use Interlocked.Increment for generating unique communication node IDs instead of GetHashCode() to avoid potential hash collisions. Co-authored-by: JanProvaznik <[email protected]>
src/Build/BackEnd/Components/Communications/NodeProviderOutOfProcTaskHost.cs
Outdated
Show resolved
Hide resolved
Address code review feedback: Use int keys directly for packet routing dictionaries (_nodeIdToPacketFactory and _nodeIdToPacketHandler) instead of going through an intermediate TaskHostNodeKey lookup. The TaskHostNodeKey is now only used where we need to identify nodes by their logical identity (HandshakeOptions + scheduledNodeId) for node existence checks. Co-authored-by: JanProvaznik <[email protected]>
|
Just as a heads up, I was blocked by some firewall rules while working on your feedback. Expand below for details. Warning Firewall rules blocked me from connecting to one or more addresses (expand for details)I tried to connect to the following addresses, but was blocked by firewall rules:
If you need me to access, download, or install something from one of these locations, you can either:
|
Reverts the simplification made in the previous commit per reviewer request. The intermediate dictionary provides cleaner lookup from communication node IDs to TaskHostNodeKey for packet routing. Co-authored-by: JanProvaznik <[email protected]>
|
Just as a heads up, I was blocked by some firewall rules while working on your feedback. Expand below for details. Warning Firewall rules blocked me from connecting to one or more addresses (expand for details)I tried to connect to the following addresses, but was blocked by firewall rules:
If you need me to access, download, or install something from one of these locations, you can either:
|
Apply reviewer feedback for O(1) packet routing performance: - Use int keys (_nodeIdToPacketFactory, _nodeIdToPacketHandler) for packet routing - Keep _nodeContexts keyed by TaskHostNodeKey for acquisition logic - Remove intermediate _nodeIdToNodeKey dictionary - Use _activeNodes with int (nodeId) instead of TaskHostNodeKey This gives type-safe Keys for managing node lifecycle while maintaining direct Integer lookups for high-frequency packet routing. Co-authored-by: JanProvaznik <[email protected]>
|
Just as a heads up, I was blocked by some firewall rules while working on your feedback. Expand below for details. Warning Firewall rules blocked me from connecting to one or more addresses (expand for details)I tried to connect to the following addresses, but was blocked by firewall rules:
If you need me to access, download, or install something from one of these locations, you can either:
|
JanProvaznik
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@copilot address comments
| /// </summary> | ||
| /// <param name="nodeId">The node to which data shall be sent.</param> | ||
| /// <param name="packet">The packet to send.</param> | ||
| public void SendData(int nodeId, INodePacket packet) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
is this method needed for anything now? if no, remove
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The SendData(int nodeId, INodePacket packet) method is required by the INodeProvider interface but not actually used for task hosts (task hosts use SendData(TaskHostNodeKey, ...) via TaskHostTask). Similar to TaskHostNodeManager.SendData, keeping it as NotImplementedException to satisfy the interface contract.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this is a bit sus, but I suppose it works, flagging this for reviewers
src/Build/BackEnd/Components/Communications/NodeProviderOutOfProcTaskHost.cs
Show resolved
Hide resolved
src/Build/BackEnd/Components/Communications/NodeProviderOutOfProcTaskHost.cs
Show resolved
Hide resolved
src/Build/BackEnd/Components/Communications/NodeProviderOutOfProcTaskHost.cs
Outdated
Show resolved
Hide resolved
- Add VerifyThrow in DisconnectFromHost to verify context exists - Restore assert in CreateNode to verify no duplicate context - Eliminate linear search in NodeContextTerminated by adding _nodeIdToNodeKey reverse mapping - Consolidate to single NodeContextTerminated(int nodeId) method - Keep SendData(int, INodePacket) throwing NotImplementedException (required by interface but not used for task hosts) Co-authored-by: JanProvaznik <[email protected]>
|
Just as a heads up, I was blocked by some firewall rules while working on your feedback. Expand below for details. Warning Firewall rules blocked me from connecting to one or more addresses (expand for details)I tried to connect to the following addresses, but was blocked by firewall rules:
If you need me to access, download, or install something from one of these locations, you can either:
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
This PR successfully refactors the TaskHost node identification system from fragile bit-packing (limiting builds to 256 nodes) to a clean, type-safe TaskHostNodeKey record struct. The refactoring removes the artificial node limit while improving code maintainability and preserving O(1) packet routing performance.
Key Changes
- Introduced
TaskHostNodeKeyrecord struct combiningHandshakeOptionsandNodeIdfor type-safe node identification - Restructured
NodeProviderOutOfProcTaskHostdictionaries to separate concerns: acquisition logic usesTaskHostNodeKey, while packet routing uses integer IDs for performance - Removed bit-packing constants and the
GenerateTaskHostNodeIdmethod fromTaskHostTask - Added comprehensive unit tests validating the new key structure including large node IDs beyond the previous 256-node limit
Reviewed changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated 2 comments.
| File | Description |
|---|---|
| src/Shared/CommunicationsUtilities.cs | Defined TaskHostNodeKey record struct and removed obsolete documentation about bit-packing constraints |
| src/Build/Instance/TaskFactories/TaskHostTask.cs | Replaced integer node ID with TaskHostNodeKey, removed bit-packing logic and related constants |
| src/Build/BackEnd/Components/Communications/NodeProviderOutOfProcTaskHost.cs | Refactored dictionary structure with atomic node ID generation, separate key-based and ID-based lookups for optimal performance |
| src/Build.UnitTests/BackEnd/TaskHostNodeKey_Tests.cs | Added 7 comprehensive tests for equality, hashing, dictionary usage, and validation of unlimited node IDs |
Comments suppressed due to low confidence (1)
src/Build/BackEnd/Components/Communications/NodeProviderOutOfProcTaskHost.cs:615
- Both branches of this 'if' statement write to the same variable - consider using '?' to express intent better.
if (!_nodeContexts.ContainsKey(nodeKey))
{
nodeCreationSucceeded = CreateNode(nodeKey, factory, handler, configuration, taskHostParameters);
}
else
{
// node already exists, so "creation" automatically succeeded
nodeCreationSucceeded = true;
}
You can also share your feedback on Copilot code review for a chance to win a $100 gift card. Take the survey.
src/Build/BackEnd/Components/Communications/NodeProviderOutOfProcTaskHost.cs
Outdated
Show resolved
Hide resolved
src/Build/BackEnd/Components/Communications/NodeProviderOutOfProcTaskHost.cs
Show resolved
Hide resolved
…rocTaskHost.cs Co-authored-by: Copilot <[email protected]>
Fixes #12676
Context
Follow-up to #12577. The taskhost node identification used bit-packing to combine
scheduledNodeId(8 bits) andHandshakeOptions(9 bits) into a single int, limiting multithreaded builds to 256 nodes. This approach was fragile and hard to maintain.Changes Made
TaskHostNodeKeyrecord struct inCommunicationsUtilities.cscombiningHandshakeOptionsandNodeIdas a clean, type-safe keyNodeProviderOutOfProcTaskHostwith optimized dictionary structure:_nodeContextskeyed byTaskHostNodeKeyfor checking if a node with given (HandshakeOptions, scheduledNodeId) exists (acquisition logic)_nodeIdToNodeKeyfor O(1) reverse lookup during node termination_nodeIdToPacketFactoryand_nodeIdToPacketHandlerkeyed by int for O(1) packet routing performance_activeNodestracks node IDs (int) for shutdown handling_nextNodeIdcounter for unique communication node ID generationTaskHostTask- removedGenerateTaskHostNodeIdmethod and associated bit-packing constantsVerifyThrowassertions inDisconnectFromHostandCreateNodeto verify context existence and prevent duplicate nodesThis gives the best of both worlds:
Testing
TaskHostNodeKey(equality, hash codes, dictionary keys, large node IDs)Notes
NODE_ID_MAX_VALUE_FOR_MULTITHREADED(255) constraint entirelySendData(int, INodePacket)throwsNotImplementedExceptionas it's required byINodeProviderinterface but not used for task hosts (similar toTaskHostNodeManager)Original prompt
💡 You can make Copilot smarter by setting up custom instructions, customizing its development environment and configuring Model Context Protocol (MCP) servers. Learn more Copilot coding agent tips in the docs.