Skip to content

Commit

Permalink
Improve dependency scanning
Browse files Browse the repository at this point in the history
  • Loading branch information
meziantou committed Oct 8, 2020
1 parent 9518b2f commit 597bdcc
Show file tree
Hide file tree
Showing 11 changed files with 363 additions and 67 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -287,3 +287,4 @@ __pycache__/
*.odx.cs
*.xsd.cs
dotCover.Output.xml
**/BenchmarkDotNet.Artifacts/
2 changes: 1 addition & 1 deletion Directory.Build.props
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

<!-- Build options -->
<PropertyGroup>
<LangVersion>preview</LangVersion>
<LangVersion>9.0</LangVersion>
<Features>strict</Features>
<AnalysisLevel>latest</AnalysisLevel>
<TreatWarningsAsErrors Condition="'$(Configuration)' != 'Debug'">true</TreatWarningsAsErrors>
Expand Down
2 changes: 1 addition & 1 deletion Directory.Build.targets
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<Project>

<!-- Ensure the latest framework is a target of the project -->
<Target Name="CheckLatestFramework" BeforeTargets="Build" Condition="$(TargetFrameworks.Contains('$(LatestTargetFramework)')) == false">
<Target Name="CheckLatestFramework" BeforeTargets="Build" Condition="$(TargetFramework.Contains('$(LatestTargetFramework)')) == false and $(TargetFrameworks.Contains('$(LatestTargetFramework)')) == false">
<Error Text="The project must target $(LatestTargetFramework)" />
</Target>

Expand Down
9 changes: 9 additions & 0 deletions Meziantou.Framework.sln
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,10 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Meziantou.Framework.Depende
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Meziantou.Framework.DependencyScanning.Tests", "tests\Meziantou.Framework.DependencyScanning.Tests\Meziantou.Framework.DependencyScanning.Tests.csproj", "{448C1A4B-ABCD-4A84-8A96-990345C4A73E}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "benchmarks", "benchmarks", "{6724AE78-2FA9-4280-B200-C897E3F80875}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DependencyScanningBenchmarks", "benchmarks\DependencyScanningBenchmarks\DependencyScanningBenchmarks.csproj", "{1BA5EE1E-C62F-4F25-91BB-C9710B5F84B6}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand Down Expand Up @@ -451,6 +455,10 @@ Global
{448C1A4B-ABCD-4A84-8A96-990345C4A73E}.Debug|Any CPU.Build.0 = Debug|Any CPU
{448C1A4B-ABCD-4A84-8A96-990345C4A73E}.Release|Any CPU.ActiveCfg = Release|Any CPU
{448C1A4B-ABCD-4A84-8A96-990345C4A73E}.Release|Any CPU.Build.0 = Release|Any CPU
{1BA5EE1E-C62F-4F25-91BB-C9710B5F84B6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{1BA5EE1E-C62F-4F25-91BB-C9710B5F84B6}.Debug|Any CPU.Build.0 = Debug|Any CPU
{1BA5EE1E-C62F-4F25-91BB-C9710B5F84B6}.Release|Any CPU.ActiveCfg = Release|Any CPU
{1BA5EE1E-C62F-4F25-91BB-C9710B5F84B6}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand Down Expand Up @@ -526,6 +534,7 @@ Global
{11D16DA2-52EF-4AE6-8AD8-CECB0CBB498D} = {E4DDFF3F-B830-4687-B3D3-E253CDAC33BF}
{C6DE2115-E164-45B5-8669-219E9B25EB3E} = {70A3E965-3866-4D23-9626-8D70E0E8729C}
{448C1A4B-ABCD-4A84-8A96-990345C4A73E} = {E4DDFF3F-B830-4687-B3D3-E253CDAC33BF}
{1BA5EE1E-C62F-4F25-91BB-C9710B5F84B6} = {6724AE78-2FA9-4280-B200-C897E3F80875}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {AA866021-BF24-4172-A655-F0E8316C38BA}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net5.0</TargetFramework>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="BenchmarkDotNet" Version="0.12.1" />
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\..\src\Meziantou.Framework.DependencyScanning\Meziantou.Framework.DependencyScanning.csproj" />
<ProjectReference Include="..\..\src\Meziantou.Framework.FullPath\Meziantou.Framework.FullPath.csproj" />
</ItemGroup>

</Project>
162 changes: 162 additions & 0 deletions benchmarks/DependencyScanningBenchmarks/Program.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,162 @@
using System.Globalization;
using System.IO;
using System.Threading.Tasks;
using BenchmarkDotNet.Attributes;
using BenchmarkDotNet.Running;
using Meziantou.Framework;
using Meziantou.Framework.DependencyScanning;

namespace DependencyScanningBenchmarks
{
[MemoryDiagnoser]
public class DependencyScannerBenchmark
{
private const int N = 100_000;
private static readonly FullPath s_directory = FullPath.GetTempPath() / "meziantou.framework" / "benchmarks" / "dependency_scanner_10_000";

[Params(1, 2, 4, 8, 16, 32)]
public int DegreeOfParallelism { get; set; }

[GlobalSetup]
public static void Initialize()
{
Directory.CreateDirectory(s_directory);
var existingFiles = Directory.GetFiles(s_directory);
if (existingFiles.Length == N)
return;

foreach (var file in existingFiles)
{
File.Delete(file);
}

for (var i = 0; i < N; i++)
{
var extension = i switch
{
< 1000 => ".cs",
< 2000 => ".md",
< 3000 => ".vb",
< 4000 => ".js",
< 5000 => ".ts",
< 6000 => ".json",
< 7000 => ".csproj",
< 8000 => ".bin",
< 9000 => ".sln",
_ => ".txt",
};

using var stream = File.Create(s_directory / ("file" + i.ToString("00000", CultureInfo.InvariantCulture) + extension));
}
}

[Benchmark]
public void MatchNoneChannel()
{
var options = new ScannerOptions
{
Scanners = new[] { new DummyScannerNeverMatch() },
RecurseSubdirectories = true,
};
GetDependenciesChannel(options).Wait();
}

[Benchmark]
public void MatchAllChannel()
{
var options = new ScannerOptions
{
Scanners = new[] { new DummyScanner() },
RecurseSubdirectories = true,
};
GetDependenciesChannel(options).Wait();
}

[Benchmark]
public void DefaultScannersChannel()
{
var options = new ScannerOptions
{
RecurseSubdirectories = true,
};
GetDependenciesChannel(options).Wait();
}

[Benchmark]
public void MatchNoneForEach()
{
var options = new ScannerOptions
{
Scanners = new[] { new DummyScannerNeverMatch() },
RecurseSubdirectories = true,
};
GetDependenciesForEach(options).Wait();
}

[Benchmark]
public void MatchAllForEach()
{
var options = new ScannerOptions
{
Scanners = new[] { new DummyScanner() },
RecurseSubdirectories = true,
};
GetDependenciesForEach(options).Wait();
}

[Benchmark]
public void DefaultScannersForEach()
{
var options = new ScannerOptions
{
RecurseSubdirectories = true,
};
GetDependenciesForEach(options).Wait();
}

private async Task GetDependenciesChannel(ScannerOptions options)
{
options.DegreeOfParallelism = DegreeOfParallelism;
await DependencyScanner.ScanDirectoryAsync(s_directory, options, _ => new ValueTask());
}

private async Task GetDependenciesForEach(ScannerOptions options)
{
options.DegreeOfParallelism = DegreeOfParallelism;
await foreach (var _ in DependencyScanner.ScanDirectoryAsync(s_directory, options))
{
}
}


private sealed class DummyScanner : DependencyScanner
{
internal static readonly Dependency Dependency = new Dependency("", "", DependencyType.Unknown, new TextLocation("", 1, 1, 1));

public override ValueTask ScanAsync(ScanFileContext context)
{
return context.ReportDependency(Dependency);
}

public override bool ShouldScanFile(CandidateFileContext file) => true;
}

private sealed class DummyScannerNeverMatch : DependencyScanner
{
public override ValueTask ScanAsync(ScanFileContext context)
{
return context.ReportDependency(new Dependency("", "", DependencyType.Unknown, new TextLocation(context.FullPath, 1, 1, 1)));
}

public override bool ShouldScanFile(CandidateFileContext file) => false;
}
}

internal static class Program
{
private static void Main()
{
BenchmarkRunner.Run<DependencyScannerBenchmark>();
}
}
}
6 changes: 6 additions & 0 deletions src/Meziantou.Framework.DependencyScanning/DependencyFound.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
using System.Threading.Tasks;

namespace Meziantou.Framework.DependencyScanning
{
public delegate ValueTask DependencyFound(Dependency dependency);
}
Loading

0 comments on commit 597bdcc

Please sign in to comment.