Refactor Node IDs for taskhost to use record struct
Fixes #12610
Context
Follow-up to #12577. The taskhost node identification used bit-packing to combine scheduledNodeId (8 bits) and HandshakeOptions (9 bits) into a single int, limiting multithreaded builds to 256 nodes. This approach was fragile and hard to maintain.
Changes Made
- New
TaskHostNodeKeyrecord struct inCommunicationsUtilities.cscombiningHandshakeOptionsandNodeIdas a clean, type-safe key - Updated
NodeProviderOutOfProcTaskHostwith 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- Added atomic
_nextNodeIdcounter for unique communication node ID generation
- Simplified
TaskHostTask- removedGenerateTaskHostNodeIdmethod and associated bit-packing constants - Improved error handling - Added
VerifyThrowassertions inDisconnectFromHostandCreateNodeto verify context existence and prevent duplicate nodes
// Before: bit-packed int with 256-node limit
_taskHostNodeId = GenerateTaskHostNodeId(_scheduledNodeId, _requiredContext);
// (scheduledNodeId << 9) | ((int)handshakeOptions & 0x1FF)
// After: clean record struct, no limit
_taskHostNodeKey = new TaskHostNodeKey(_requiredContext, _scheduledNodeId);
This gives the best of both worlds:
- Maintainability: Type-safe Keys for managing node lifecycle and acquisition
- Performance: Direct Integer lookups for the high-frequency packet routing hot path
Testing
- Added 7 unit tests for
TaskHostNodeKey(equality, hash codes, dictionary keys, large node IDs) - All 86 existing TaskHost tests pass
Notes
- Removes the
NODE_ID_MAX_VALUE_FOR_MULTITHREADED(255) constraint entirely SendData(int, INodePacket)throwsNotImplementedExceptionas it's required byINodeProviderinterface but not used for task hosts (similar toTaskHostNodeManager)
Original prompt
This section details on the original issue you should resolve
<issue_title>[multithreaded] Refactor Node IDs for taskhost</issue_title> <issue_description>followup to dotnet/msbuild#12577 Refactor src/Build/BackEnd/Components/Communications/NodeProviderOutOfProcTaskHost.cs , HandshakeOptions to use record struct as a key to nodes to increase maintanability and remove limitation to 256 nodes.</issue_description>
Comments on the Issue (you are @copilot in this section)
- Fixes dotnet/msbuild#12610
💡 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.
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:
rcxvsblobprodcus328.vsblob.vsassets.io
- Triggering command:
/home/REDACTED/work/msbuild/msbuild/artifacts/bin/bootstrap/core/dotnet dotnet test src/Build.UnitTests/Microsoft.Build.Engine.UnitTests.csproj --filter FullyQualifiedName~TaskHost --no-build -v n(dns block)If you need me to access, download, or install something from one of these locations, you can either:
- Configure Actions setup steps to set up my environment, which run before the firewall is enabled
- Add the appropriate URLs or hosts to the custom allowlist in this repository's Copilot coding agent settings (admins only)
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:
rcxvsblobprodcus328.vsblob.vsassets.io
- Triggering command:
/home/REDACTED/work/msbuild/msbuild/artifacts/bin/bootstrap/core/dotnet dotnet test src/Build.UnitTests/Microsoft.Build.Engine.UnitTests.csproj --filter FullyQualifiedName~TaskHost --no-build -v n(dns block)If you need me to access, download, or install something from one of these locations, you can either:
- Configure Actions setup steps to set up my environment, which run before the firewall is enabled
- Add the appropriate URLs or hosts to the custom allowlist in this repository's Copilot coding agent settings (admins only)
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:
rcxvsblobprodcus328.vsblob.vsassets.io
- Triggering command:
/home/REDACTED/work/msbuild/msbuild/artifacts/bin/bootstrap/core/dotnet dotnet test src/Build.UnitTests/Microsoft.Build.Engine.UnitTests.csproj --filter FullyQualifiedName~TaskHost --no-build -v n(dns block)If you need me to access, download, or install something from one of these locations, you can either:
- Configure Actions setup steps to set up my environment, which run before the firewall is enabled
- Add the appropriate URLs or hosts to the custom allowlist in this repository's Copilot coding agent settings (admins only)
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:
rcxvsblobprodcus328.vsblob.vsassets.io
- Triggering command:
/home/REDACTED/work/msbuild/msbuild/artifacts/bin/bootstrap/core/dotnet dotnet test src/Build.UnitTests/Microsoft.Build.Engine.UnitTests.csproj --filter FullyQualifiedName~TaskHost --no-build -v n(dns block)If you need me to access, download, or install something from one of these locations, you can either:
- Configure Actions setup steps to set up my environment, which run before the firewall is enabled
- Add the appropriate URLs or hosts to the custom allowlist in this repository's Copilot coding agent settings (admins only)
https://devdiv.visualstudio.com/DevDiv/_git/VS/pullrequest/695704 passed