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.
///