diff --git a/src/Build/BackEnd/Components/BuildRequestEngine/BuildRequestEngine.cs b/src/Build/BackEnd/Components/BuildRequestEngine/BuildRequestEngine.cs index dd806ec41ce..a61a5e7b6c9 100644 --- a/src/Build/BackEnd/Components/BuildRequestEngine/BuildRequestEngine.cs +++ b/src/Build/BackEnd/Components/BuildRequestEngine/BuildRequestEngine.cs @@ -343,7 +343,7 @@ public void SubmitBuildRequest(BuildRequest request) QueueAction( () => { - ErrorUtilities.VerifyThrow(_status != BuildRequestEngineStatus.Shutdown && _status != BuildRequestEngineStatus.Uninitialized, "Engine loop not yet started, status is {0}.", _status); + ErrorUtilities.VerifyThrow(_status != BuildRequestEngineStatus.Shutdown && _status != BuildRequestEngineStatus.Uninitialized, "Engine loop not yet started, status is {0}.", _status.Box()); TraceEngine("Request {0}({1}) (nr {2}) received and activated.", request.GlobalRequestId, request.ConfigurationId, request.NodeRequestId); ErrorUtilities.VerifyThrow(!_requestsByGlobalRequestId.ContainsKey(request.GlobalRequestId), "Request {0} is already known to the engine.", request.GlobalRequestId); @@ -363,7 +363,7 @@ public void SubmitBuildRequest(BuildRequest request) config.RetrieveFromCache(); ((IBuildResults)resultToReport).SavedCurrentDirectory = config.SavedCurrentDirectory; ((IBuildResults)resultToReport).SavedEnvironmentVariables = config.SavedEnvironmentVariables; - if (!request.BuildRequestDataFlags.HasFlag(BuildRequestDataFlags.IgnoreExistingProjectState)) + if ((request.BuildRequestDataFlags & BuildRequestDataFlags.IgnoreExistingProjectState) != BuildRequestDataFlags.IgnoreExistingProjectState) { resultToReport.ProjectStateAfterBuild = config.Project; } @@ -414,7 +414,7 @@ public void UnblockBuildRequest(BuildRequestUnblocker unblocker) QueueAction( () => { - ErrorUtilities.VerifyThrow(_status != BuildRequestEngineStatus.Shutdown && _status != BuildRequestEngineStatus.Uninitialized, "Engine loop not yet started, status is {0}.", _status); + ErrorUtilities.VerifyThrow(_status != BuildRequestEngineStatus.Shutdown && _status != BuildRequestEngineStatus.Uninitialized, "Engine loop not yet started, status is {0}.", _status.Box()); ErrorUtilities.VerifyThrow(_requestsByGlobalRequestId.ContainsKey(unblocker.BlockedRequestId), "Request {0} is not known to the engine.", unblocker.BlockedRequestId); BuildRequestEntry entry = _requestsByGlobalRequestId[unblocker.BlockedRequestId]; @@ -467,7 +467,11 @@ public void UnblockBuildRequest(BuildRequestUnblocker unblocker) } else { - TraceEngine("Request {0}({1}) (nr {2}) is no longer waiting on nr {3} (UBR). Results are {4}.", entry.Request.GlobalRequestId, entry.Request.ConfigurationId, entry.Request.NodeRequestId, result.NodeRequestId, result.OverallResult); + // PERF: Explicitly check the debug flag here so that we don't pay the cost for getting OverallResult + if (_debugDumpState) + { + TraceEngine("Request {0}({1}) (nr {2}) is no longer waiting on nr {3} (UBR). Results are {4}.", entry.Request.GlobalRequestId, entry.Request.ConfigurationId, entry.Request.NodeRequestId, result.NodeRequestId, result.OverallResult); + } // Update the configuration with targets information, if we received any and didn't already have it. if (result.DefaultTargets != null) @@ -515,7 +519,7 @@ public void ReportConfigurationResponse(BuildRequestConfigurationResponse respon QueueAction( () => { - ErrorUtilities.VerifyThrow(_status != BuildRequestEngineStatus.Shutdown && _status != BuildRequestEngineStatus.Uninitialized, "Engine loop not yet started, status is {0}.", _status); + ErrorUtilities.VerifyThrow(_status != BuildRequestEngineStatus.Shutdown && _status != BuildRequestEngineStatus.Uninitialized, "Engine loop not yet started, status is {0}.", _status.Box()); TraceEngine("Received configuration response for node config {0}, now global config {1}.", response.NodeConfigurationId, response.GlobalConfigurationId); ErrorUtilities.VerifyThrow(_componentHost != null, "No host object set"); @@ -1449,9 +1453,94 @@ private void QueueAction(Action action, bool isLastTask) } } - /// - /// Method used for debugging purposes. - /// + private void TraceEngine(string format, ulong arg) + { + if (_debugDumpState) + { + TraceEngine(format, [arg]); + } + } + + private void TraceEngine(string format, int arg) + { + if (_debugDumpState) + { + TraceEngine(format, [arg]); + } + } + + private void TraceEngine(string format, int arg1, BuildRequestEngineStatus arg2) + { + if (_debugDumpState) + { + TraceEngine(format, [arg1, arg2.Box()]); + } + } + + private void TraceEngine(string format, int arg1, int arg2) + { + if (_debugDumpState) + { + TraceEngine(format, [arg1, arg2]); + } + } + + private void TraceEngine(string format, ulong arg1, ulong arg2) + { + if (_debugDumpState) + { + TraceEngine(format, [arg1, arg2]); + } + } + + private void TraceEngine(string format, int arg1, int arg2, int arg3) + { + if (_debugDumpState) + { + TraceEngine(format, [arg1, arg2, arg3]); + } + } + + private void TraceEngine(string format, int arg1, int arg2, string arg3) + { + if (_debugDumpState) + { + TraceEngine(format, [arg1, arg2, arg3]); + } + } + + private void TraceEngine(string format, int arg1, int arg2, int arg3, string arg4) + { + if (_debugDumpState) + { + TraceEngine(format, [arg1, arg2, arg3, arg4]); + } + } + + private void TraceEngine(string format, int arg1, int arg2, int arg3, BuildRequestEntryState arg4) + { + if (_debugDumpState) + { + TraceEngine(format, [arg1, arg2, arg3, arg4]); + } + } + + private void TraceEngine(string format, int arg1, int arg2, int arg3, int arg4, int arg5) + { + if (_debugDumpState) + { + TraceEngine(format, [arg1, arg2, arg3, arg4, arg5]); + } + } + + private void TraceEngine(string format, int arg1, int arg2, int arg3, int arg4, BuildResultCode arg5) + { + if (_debugDumpState) + { + TraceEngine(format, [arg1, arg2, arg3, arg4, arg5]); + } + } + private void TraceEngine(string format, params object[] stuff) { if (_debugDumpState) diff --git a/src/Build/BackEnd/Components/BuildRequestEngine/IBuildRequestEngine.cs b/src/Build/BackEnd/Components/BuildRequestEngine/IBuildRequestEngine.cs index fac725d8149..75708489039 100644 --- a/src/Build/BackEnd/Components/BuildRequestEngine/IBuildRequestEngine.cs +++ b/src/Build/BackEnd/Components/BuildRequestEngine/IBuildRequestEngine.cs @@ -86,6 +86,38 @@ internal enum BuildRequestEngineStatus Shutdown } + /// + /// Provides boxed representations of the enumeration values. + /// + /// This class offers pre-boxed objects for each status value to avoid repeated allocations due to boxing + /// when frequently accessing these status values. It also includes an extension method to retrieve the + /// boxed object corresponding to a given . + internal static class BuildRequestEngineStatusBoxes + { + public static readonly object UninitializedBox = BuildRequestEngineStatus.Uninitialized; + public static readonly object IdleBox = BuildRequestEngineStatus.Idle; + public static readonly object ActiveBox = BuildRequestEngineStatus.Active; + public static readonly object WaitingBox = BuildRequestEngineStatus.Waiting; + public static readonly object ShutdownBox = BuildRequestEngineStatus.Shutdown; + + /// + /// Gets the canonical boxed object for the specified . + /// + /// The desired . + /// The boxed . + /// Thrown when is outside the range of + /// defined values. + public static object Box(this BuildRequestEngineStatus status) => status switch + { + BuildRequestEngineStatus.Uninitialized => UninitializedBox, + BuildRequestEngineStatus.Idle => IdleBox, + BuildRequestEngineStatus.Active => ActiveBox, + BuildRequestEngineStatus.Waiting => WaitingBox, + BuildRequestEngineStatus.Shutdown => ShutdownBox, + _ => throw new ArgumentOutOfRangeException(nameof(status)), + }; + } + /// /// Objects implementing this interface may be used by a Node to process build requests /// and generate build results. diff --git a/src/Shared/ErrorUtilities.cs b/src/Shared/ErrorUtilities.cs index 728445efe07..ed4a38b1650 100644 --- a/src/Shared/ErrorUtilities.cs +++ b/src/Shared/ErrorUtilities.cs @@ -196,6 +196,17 @@ internal static void VerifyThrow([DoesNotReturnIf(false)] bool condition, string } } + /// + /// Overload for one string format argument. + /// + internal static void VerifyThrow([DoesNotReturnIf(false)] bool condition, string unformattedMessage, int arg0) + { + if (!condition) + { + ThrowInternalError(unformattedMessage, arg0); + } + } + /// /// Overload for one string format argument. /// @@ -207,6 +218,17 @@ internal static void VerifyThrow([DoesNotReturnIf(false)] bool condition, string } } + /// + /// Overload for two string format arguments. + /// + internal static void VerifyThrow([DoesNotReturnIf(false)] bool condition, string unformattedMessage, int arg0, int arg1) + { + if (!condition) + { + ThrowInternalError(unformattedMessage, arg0, arg1); + } + } + /// /// Overload for two string format arguments. ///