-
Notifications
You must be signed in to change notification settings - Fork 1.4k
Fix TaskParameterTaskItem serialization perf #11638
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
lol probably broke something while pulling this out of my RAR branch, will check UT failures later today |
5096b1b
to
57f0123
Compare
Updated with profile traces now that I've fully isolated it from other perf stuff. Tests passing so should be good to go 👍 |
@@ -891,6 +763,25 @@ public void CopyMetadataTo(ITaskItem destinationItem) | |||
// between items, and need to know the source item where the metadata came from | |||
string originalItemSpec = destinationItem.GetMetadata("OriginalItemSpec"); | |||
|
|||
#if !TASKHOST |
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.
Tbh not sure why IMetadataContainer
is conditioned out of the taskhost beside the extra source file (compiles fine with it), but I've kept it here anyways.
} | ||
#endif | ||
|
||
destinationItemAsMetadataContainer.ImportMetadata(metadataToImport); |
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.
Based on that profile showing SetMetadata("OrignalItemSpec")
adding still time under here, maybe worth joining it into the IEnumerable
to avoid immediately copying a new ImmutableDictionary
right after this block - haven't checked to see if IEnumerable.Concat()
or spread operator works efficiently or ends up allocating a collection. Otherwise a local function + yield return
would work
Fixes
Fixes several hotspots I found while profiling RAR service serialization.
Changes Made
TaskParameterTaskItem
is created to wrap an existing TaskItem, but then of its metadata is parsed one again right before serializationMSBuildNameIgnoreCaseComparer.Default
(by moving it into Framework`ITaskItem2.CloneCustomMetadataEscaped()
. If this is aUtilities.TaskItem
coming back from a task, doing an accessor check is non-negligible overhead due toCopyOnWriteDictionary
.ITranslator
APIs over manually checking each direction or reimplementing methods, and letTaskParameterTaskItem
handle its own serialization.A bunch of small improvements but they add up. Since the out of proc TaskHost is the only piece currently using this, here's some profiles off my RAR service builds.
TaskParameterTaskItem.CopyMetadataTo()
This is often hit by
ReferenceTable.SetItemMetadata
in RAR. This fix here was to useIMetadataContainer.ImportMetadata()
bulk set, sinceImmutableDictionary
performs better when operations are batched.Before:


After:
Double
ITaskItem
parsingEssentially when in the write direction the old code would construct a
TaskParameterTaskItem
, but later cast it to ITaskItem and parse everything out again. You can see this here whereCloneCustomMetadataEscaped()
is hit even though by this point we've already extracted the externalTaskItem
to our own instance.Before:


After:
ItemSpec
unescaped value cachingAdded a simple cache around
ItemSpec
property accesses. Might be worth porting this intoProjectItemInstance.TaskItem
andUtilities.TaskItem
since this is hit very often.I'm showing this one as a backtrace to show where this is hit.
Before:


After:
This actually appears to just no-op most of the time since most of the time is spent in String.IndexOf():
