-
Notifications
You must be signed in to change notification settings - Fork 1.4k
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
Optimize logging by moving message importance checks earlier #6381
Optimize logging by moving message importance checks earlier #6381
Conversation
0fc5a81
to
5cfb9f6
Compare
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.
I like it! Thanks for making these changes!
IBuildEngine9 | ||
{ | ||
/// <summary> | ||
/// True if the "secret" environment variable MSBUILDNOINPROCNODE is set. | ||
/// </summary> | ||
private static bool s_onlyUseOutOfProcNodes = Environment.GetEnvironmentVariable("MSBUILDNOINPROCNODE") == "1"; | ||
private static bool s_onlyUseOutOfProcNodes = Traits.Instance.ForceOutOfProcBuildExecution; |
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.
Could this break someone if they set the MSBUILDNOINPROCNODE flag partway through the build? I vaguely remember a case similar to that.
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.
As with many escape hatches, we may get into an interesting state if different processes run with different environment variables. I don't think this change is making much of a difference, though, as we're still reading the value from the current process, potentially at a different time. To break something, there would have to be an entity setting the variable on the current running process which is very unlikely.
The ultimate fix would be to take a snapshot of the relevant environment variables in the main node, and either make them part of the handshake (connect only to nodes running with the same variables), or be sending them with requests (to avoid reading them in remote nodes altogether). Honestly, it looks like an overkill.
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.
Found the bug I was thinking of:
https://devdiv.visualstudio.com/DevDiv/_workitems/edit/1197992
I'm not sure we should support this sort of thing, but felt I should call it out.
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.
Oh, wow, if we backported a fix for this in the past, let's definitely not change the behavior. I'll revert the change. Thank you!
Do you think we should tack on a fix for #6305 (expose LogTaskInputs to tasks) in this PR or separately? It's very similar in nature and should be easy to add if we're modifying the build engine interface anyway. Of course use the different API but the intention is the same. |
The effects and solutions seem similar, but the problems they're trying to solve feel different enough to me that I'd slightly prefer them in separate PRs. One tries to eliminate unnecessary abortive attempts at logging messages, and the other eliminates duplicate log messages by fixing a prior bug. I don't mind if you want to add it here, though, and I think both are good improvements. |
I'm just not sure what's the good design here, I guess it's up to you guys to decide on one. It involves how we plan to evolve IBuildEngine* in the future. |
ref/Microsoft.Build.Utilities.Core/net/Microsoft.Build.Utilities.Core.cs
Outdated
Show resolved
Hide resolved
b30ab8e
to
a733558
Compare
I still have to address a few comments but I wanted to get the new |
600ece5
to
f4f4322
Compare
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.
Version number (probably best)/dictionary/set/something as discussed in PR reviews, but otherwise LGTM!
Though I'm wondering in retrospect—why did we decide we needed IBuildEngine10 rather than just having "BuildEngineInterface" with a version that we can add things to? (Also may want to rename it, since it isn't technically an interface.)
I wasn't paying much attention, but a reminder that I'm still super interested in exposing LogTaskInputs to tasks, so RAR can turn off its custom logging if we're logging all inputs anyway: #6305 Whatever design we come up with for IBuildEngine*, please keep the scenario ^^ in mind as well. Pretty much please stick Not saying it should be a part of this PR though! Thanks! |
Will definitely do, @KirillOsenkov. Likely as a separate PR. |
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.
Though I'm wondering in retrospect—why did we decide we needed IBuildEngine10 rather than just having "BuildEngineInterface" with a version that we can add things to?
The reference in which the build engine is passed around is typed as IBuildEngine
. To be able to use a functionality added later, the caller has to cast to another type. This type cannot be a class because IBuildEngine
is already implemented by a class - a different one, obviously - and we would basically say that all implementors must derive from this base class, which would be a really bad practice. And impossible in many cases, like when the implementation has an important base class already (hello MarshalByRefObject
!).
So to avoid the interface hop, we would have to add a BuildEngineInterface
property or parameter to all places that currently take or return IBuildEngine
. That would be pretty big API change, maybe with unwanted side-effects. I hope I understood the question, please let me know if you had something else in mind.
(Also may want to rename it, since it isn't technically an interface.)
Yes, not an interface so it doesn't have the leading I
. Though kind of like an interface, hence the trailing Interface
. I'm totally open to suggestions!
Pull request contains merge conflicts. |
6d2daf7
to
7a40091
Compare
66af2bd
to
906f2eb
Compare
…leForwardingLogger
bf1a7d9
to
bdf6b18
Compare
Fixes #5992
Context
Some tasks spend a lot of time producing detailed log messages that end up going nowhere when building on the command line with Normal or Minimum verbosity. The goal of this PR is to expose an API for tasks to call to answer the question "Are log messages of a given importance going to be consumed by a logger or should I not bother doing the work to create the output and skip calling
LogMessage
altogether?"Changes Made
Added a public method named
LogsMessagesOfImportance
onTaskLoggingHelper
to answer the question above. This PR focuses on command line scenarios such asdotnet build
but the logic could be easily used/extended to work with 3rd party loggers (in IDEs for example) if we introduce a mechanism by which loggers promise to ignore too verbose messages. The solution presented herein is a bolt-on, making minimum changes to the existing logging infra. Third party loggers are assumed to be potentially logging everything so if at least one such logger is registered, the optimization is disabled.The new method is used internally by
TaskLoggingHelper
and by the otherwise spammy RAR task.Testing
Existing and new unit tests, manual verification on command line as well as in Visual Studio.
Performance testing has shown ~18 ms improvement in RAR run-time alone when building a single project with
dotnet build
.Notes
This PR also introduces a new class
EngineServices
to serve as a replacement for theIBuildEngineN
interfaces.