Skip to content

Batch metadata updates for better performance (attempt 2)#8240

Merged
rainersigwald merged 5 commits intodotnet:mainfrom
marcin-krystianc:marcink-20221213-addrange
Mar 28, 2023
Merged

Batch metadata updates for better performance (attempt 2)#8240
rainersigwald merged 5 commits intodotnet:mainfrom
marcin-krystianc:marcink-20221213-addrange

Conversation

@marcin-krystianc
Copy link
Copy Markdown
Contributor

Improves dotnet/sdk#27738
It is another attempt to introduce changes proposed in #8098, which was reverted due to a bug.

Context

When profiling "design-time-builds" (see dotnet/sdk#27738) one method that stands out in the performance profiler is a method called GatherTaskOutputs. It copies the output of the executed task into a new ProjectItemInstance. Copying the output metadata involves creating and populating the ImmutableDicitionary in the newly created ProjectItemInstance. The copying process turns out to be a noticeably slow operation.

Changes Made

Instead of copying metadata properties one by one, all properties will be copied with a single SetItems operation.
According to BenchmarkDotNet using a single operation to populate the ImmutableDictionary is twice as fast.

Testing

Benchmarking using scenario from dotnet/sdk#27738 (comment).

before:
Time Elapsed 00:01:23.19
Time Elapsed 00:01:23.88
Time Elapsed 00:01:23.08
Time Elapsed 00:01:23.21
Time Elapsed 00:01:23.15

after:
Time Elapsed 00:01:20.66
Time Elapsed 00:01:20.98
Time Elapsed 00:01:20.91
Time Elapsed 00:01:20.97
Time Elapsed 00:01:20.89

Notes

Previous PR got reverted due to a bug in checking whether the copied metadata is one of the well-known attributes (we were checking value, but we should check the key instead). I've tried to add a test that validates that we filter out metadata items that have a well-known name, to prevent any such mistake in the future. Unfortunately, it is a non-easy scenario to reproduce in a test. MSBuild's code prevents the creation of custom metadata with a reserved name (e.g. during project parsing or in the TaskItem class). The only way to work around it seems to be to implement a custom ITaskItem class, but that feels to be too much for a single test.

Copy link
Copy Markdown
Member

@rainersigwald rainersigwald left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have a vague recollection that when we first hit the bug, I tried a private build with a change much like this and it didn't work. However, I don't see how that could be possible so I suspect I set up the repro badly (like didn't copy over my private bits right or something).

Can you please add a regression-test case that uses a special name for the value as in #8153? Otherwise looks great!

@marcin-krystianc
Copy link
Copy Markdown
Contributor Author

marcin-krystianc commented Jan 20, 2023

Hi @rainersigwald ,

I've come up with such code:

[Fact]
public void IsWellKnownAttributeValuePreserved()
{
    ObjectModelHelpers.DeleteTempProjectDirectory();

    ObjectModelHelpers.CreateFileInTempProjectDirectory("Myapp.proj", @"
        <Project ToolsVersion=`msbuilddefaulttoolsversion` xmlns=`msbuildnamespace`>
          <Target Name =`Repro`>
            <CreateItem Include=`*.txt` AdditionalMetadata=`MyProperty=Identity`>
              <Output TaskParameter=`Include` ItemName=`TestItem`/>
            </CreateItem>
            <Error Text=`@(TestItem)` Condition=""'%(MyProperty)' != 'Identity' ""/>
          </Target>
        </Project>
        ");

    ObjectModelHelpers.CreateFileInTempProjectDirectory("Foo.txt", "foo");
    MockLogger logger = new MockLogger(_testOutput);
    ObjectModelHelpers.BuildTempProjectFileExpectSuccess("Myapp.proj", logger);
}

I've confirmed that it would fail on #8098.
Do you think it is ok, or there is anything to be added?

Copy link
Copy Markdown
Member

@rainersigwald rainersigwald left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants