私は msbuild プロジェクトを作成しています。タスクの 1 つは、提供されたファイル マスクのいずれかを満たすディレクトリ内のすべてのファイルを検索することです。
/属性にItem
複数のワイルドカードを使用して1 行だけを作成したとしても、msbuildはこれらのワイルドカードごとにディレクトリ hiearacrhy 全体を完全に再スキャンすることに気付きました。Include
Exclude
したがって、ディレクトリ全体のスキャン($Path)\**
にたとえば 6 秒かかる場合、ワイルドカードを 10 個だけ使用すると 1 分かかります。これは私の目的ではかなり遅いです。
ファイルのスキャンは非常に遅い操作であると思いますが、マスク比較 (ファイル名ごとに 1 つまたは 10 または 1000) はより高速になるはずです。
ここに、私が何を意味するかを示すサンプル 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 を「ウォームアップ」し、可能なものをすべてキャッシュに入れます。次に、1 つのマスクを探し、次に 2 つのマスク (1 つのインクルードと 1 つの除外)、次に 5 つのマスク (2 つのインクルードと 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 が同じファイル階層ですべてのマスクを 1 つずつ実際に検索することを示す whichなどを使用して、同様の結果を確認できます。
一般的に、私が探しているのは、タスクCheckFive
とほぼ同じ時間をターゲットに設定する方法です。CheckOne
ファイルの列挙が遅いことを証明するために、ディレクトリ階層を1つだけ列挙し、各ファイルにいくつかのマスクを適用するカスタムタスクを作成しました-はい、妥当な数のマスクに対して多かれ少なかれ同じ時間がかかります.
しかし、私はまだ何か間違ったことをしていると思います.純粋なmsbuildで同じ効率を達成できますか?