我正在创建msbuild项目,其中一项任务是查找满足所提供的任何文件掩码的目录中的所有文件。
我意识到,即使我在Item
/ Include
属性中创建了几个带有多个通配符的单行Exclude
,msbuild也会完全重新扫描整个目录hiearacrhy 每个< / strong>这些通配符。
因此,如果像($Path)\**
这样的完整目录扫描需要6秒钟,那么仅使用10个通配符就会使它长达一分钟 - 这对我的目的而言相当缓慢。
我认为扫描文件实际上是慢操作,而屏蔽比较(每个文件名一个或十个或一千个)应该更多更快 - 所以我看起来for是有效扫描多个文件掩码的目录层次结构的解决方案。
这是示例msbuild项目,它显示了我的意思:
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" DefaultTargets="Build">
<PropertyGroup>
<MyPath>C:\Windows</MyPath>
</PropertyGroup>
<Target Name="Build" DependsOnTargets="Warmup;CheckOne;CheckTwo;CheckFive">
</Target>
<Target Name="Warmup">
<ItemGroup>
<Item1 Include="$(MyPath)\**" />
</ItemGroup>
</Target>
<Target Name="CheckOne">
<ItemGroup>
<Item2 Include="$(MyPath)\**\*.exe" />
</ItemGroup>
</Target>
<Target Name="CheckTwo">
<ItemGroup>
<Item2 Include="$(MyPath)\**\*.dll" Exclude="$(MyPath)\**\System32\**" />
</ItemGroup>
</Target>
<Target Name="CheckFive">
<ItemGroup>
<Item3 Include="$(MyPath)\**\*.exe;$(MyPath)\**\*.dll" Exclude="$(MyPath)\**\System32\**;$(MyPath)\**\SysWOW64\**;$(MyPath)\**\winsxs\**" />
</ItemGroup>
</Target>
</Project>
首先它扫描完整的Windows目录以“预热”FS并将其可以放入缓存,然后查找单个掩码,然后查找两个掩码(一个包含和一个排除),然后查找五个掩码(两个包含和3排除)。
当我使用/v:diag
开关运行时,我会收到以下时间:
Target Performance Summary:
0 ms Build 1 calls
6196 ms CheckOne 1 calls
7942 ms Warmup 1 calls
15030 ms CheckTwo 1 calls
39249 ms CheckFive 1 calls
所以我看到的是,平均每个面具会增加6-8秒的结果。
例如,使用procmon
可以看到类似的结果,这表明msbuild确实在同一文件层次结构上逐个搜索所有掩码。
一般来说,我正在寻找的是 - 如何使CheckFive
目标与CheckOne
任务同时或多或少地接受。
为了证明自己枚举文件很慢,我创建了自定义任务,它只列举了一个目录层次结构,并对每个文件应用了几个掩码 - 是的,对于任何合理数量的掩码,它需要或多或少的同一时间。
但我仍然认为我做错了什么 - 我能用纯msbuild达到相同的效率吗?