[resizetizer] fix a build performance issue (#24453)

I was testing a .NET MAUI project template in Visual Studio on a
Windows DevBox, and I noticed a target taking *a lot* of time:

    ResizetizeImages 1.302s
    Skipping target "ResizetizeImages" because all output files are up-to-date with respect to the input files.

This is happening on incremental builds with no changes. This is even
worse for Android, because it runs twice: one for build and one for
deploy.

The `ResizetizeImages` MSBuild target is *skipped*, why is it slow?!?

To "debug" this, I added this ugly, one-liner between every
`<ItemGroup>` in the target:

    <ItemGroup>
      </ItemGroup><PropertyGroup><_Time>$([System.DateTime]::Now.ToString('THH:mm:ss.fffffffZ'))</_Time></PropertyGroup><ItemGroup>
      <_MauiImageToProcess Include="@(MauiImage)" Exclude="$(DefaultItemExcludes)" />
      </ItemGroup><PropertyGroup><_Time>$([System.DateTime]::Now.ToString('THH:mm:ss.fffffffZ'))</_Time></PropertyGroup><ItemGroup>
      <!-- more item groups -->
      </ItemGroup><PropertyGroup><_Time>$([System.DateTime]::Now.ToString('THH:mm:ss.fffffffZ'))</_Time></PropertyGroup><ItemGroup>
    </ItemGroup>

(I found the `/profileevaluation` switch didn't help me here)

This led me to find the problematic line, is this one:

    <_MauiImageToProcess Include="@(MauiImage)" Exclude="$(DefaultItemExcludes)" />

Where `$(DefaultItemExcludes)` is:

    DefaultItemExcludes = ;bin\Debug\/**;obj\Debug\/**;bin\/**;obj\/**;**/*.user;**/*.*proj;**/*.sln;**/*.vssscc;**/.DS_Store

This was introduced in a92fd1d8 to fix `.DS_Store` files in the folder:

    <MauiImage Include="Resources\Images\*" />

(This is in the .NET MAUI project template).

What is happening is:

* MSBuild expands these 9 wildcards to a lot of files

* MSBuild now has to filter out the files that are in `@(MauiImage)`

If I simply reduce this to:

    <_MauiImageToProcess Include="@(MauiImage)" Exclude="**/.DS_Store" />

It still takes 177ms after this change, because MSBuild has to
do a recursive file listing of the current project.

So, we can do better. We can use `Condition` instead:

    <_MauiImageToProcess Include="@(MauiImage)" Condition=" '%(FileName)%(Extension)' != '.DS_Store' " />

After these changes, the target now takes:

    ResizetizeImages 6ms

I can't think of what this would break, as I don't think any of these
files are in `Resources\Images`:

    DefaultItemExcludes = ;bin\Debug\/**;obj\Debug\/**;bin\/**;obj\/**;**/*.user;**/*.*proj;**/*.sln;**/*.vssscc;**/.DS_Store

The only problem I can think of would be if someone sets
`$(DefaultItemExcludes)` to a custom value, and I think saving the
build time is worth it.
This commit is contained in:
Jonathan Peppers 2024-08-27 12:12:24 -05:00 коммит произвёл GitHub
Родитель 033b01abb2
Коммит 1b0014048d
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: B5690EEEBB952194
1 изменённых файлов: 1 добавлений и 1 удалений

Просмотреть файл

@ -618,7 +618,7 @@
DependsOnTargets="$(ResizetizeDependsOnTargets)">
<ItemGroup>
<_MauiImageToProcess Include="@(MauiImage)" Exclude="$(DefaultItemExcludes)" />
<_MauiImageToProcess Include="@(MauiImage)" Condition=" '%(FileName)%(Extension)' != '.DS_Store' " />
</ItemGroup>
<DetectInvalidResourceOutputFilenamesTask