up
Some checks failed
AOC Guard CI / aoc-guard (push) Has been cancelled
AOC Guard CI / aoc-verify (push) Has been cancelled
Docs CI / lint-and-preview (push) Has been cancelled
Policy Lint & Smoke / policy-lint (push) Has been cancelled

This commit is contained in:
StellaOps Bot
2025-11-27 23:44:42 +02:00
parent ef6e4b2067
commit 3b96b2e3ea
298 changed files with 47516 additions and 1168 deletions

View File

@@ -0,0 +1,48 @@
using StellaOps.Scanner.Analyzers.Lang;
namespace StellaOps.Scanner.Analyzers.Lang.Php.Benchmarks;
internal static class PhpBenchmarkShared
{
public static string ResolveRepoRoot()
{
var fromEnv = Environment.GetEnvironmentVariable("STELLAOPS_REPO_ROOT");
if (!string.IsNullOrWhiteSpace(fromEnv) && Directory.Exists(fromEnv))
{
return Path.GetFullPath(fromEnv);
}
var directory = Path.GetFullPath(AppContext.BaseDirectory);
while (!string.IsNullOrEmpty(directory))
{
if (Directory.Exists(Path.Combine(directory, ".git")))
{
return directory;
}
var parent = Directory.GetParent(directory)?.FullName;
if (string.IsNullOrEmpty(parent) || string.Equals(parent, directory, StringComparison.Ordinal))
{
break;
}
directory = parent;
}
throw new InvalidOperationException("Unable to locate StellaOps repository root. Set STELLAOPS_REPO_ROOT.");
}
public static string ResolveFixture(string repoRoot, params string[] segments)
{
var path = Path.Combine(new[] { repoRoot }.Concat(segments).ToArray());
if (!Directory.Exists(path))
{
throw new DirectoryNotFoundException($"Fixture path {path} not found.");
}
return path;
}
public static LanguageAnalyzerContext CreateContext(string rootPath)
=> new(rootPath, TimeProvider.System);
}

View File

@@ -0,0 +1,83 @@
using BenchmarkDotNet.Attributes;
using StellaOps.Scanner.Analyzers.Lang;
using StellaOps.Scanner.Analyzers.Lang.Php;
using StellaOps.Scanner.Analyzers.Lang.Php.Benchmarks;
/// <summary>
/// Performance benchmarks for PHP language analyzer.
/// </summary>
/// <remarks>
/// Expected latency budgets (per fixture type):
/// - Basic: < 10ms
/// - Laravel extended: < 50ms
/// - Symfony: < 50ms
/// - WordPress: < 30ms
/// - Legacy: < 10ms
/// - PHAR: < 20ms
/// - Container: < 30ms
/// </remarks>
[MemoryDiagnoser]
public class PhpLanguageAnalyzerBenchmark
{
private LanguageAnalyzerEngine _engine = default!;
private LanguageAnalyzerContext _basicContext = default!;
private LanguageAnalyzerContext _laravelContext = default!;
private LanguageAnalyzerContext _symfonyContext = default!;
private LanguageAnalyzerContext _wordpressContext = default!;
private LanguageAnalyzerContext _legacyContext = default!;
private LanguageAnalyzerContext _pharContext = default!;
private LanguageAnalyzerContext _containerContext = default!;
[GlobalSetup]
public void Setup()
{
_engine = new LanguageAnalyzerEngine(new ILanguageAnalyzer[] { new PhpLanguageAnalyzer() });
var repoRoot = PhpBenchmarkShared.ResolveRepoRoot();
var fixturesBase = PhpBenchmarkShared.ResolveFixture(
repoRoot,
"src",
"Scanner",
"__Tests",
"StellaOps.Scanner.Analyzers.Lang.Php.Tests",
"Fixtures",
"lang",
"php");
_basicContext = PhpBenchmarkShared.CreateContext(Path.Combine(fixturesBase, "basic"));
_laravelContext = PhpBenchmarkShared.CreateContext(Path.Combine(fixturesBase, "laravel-extended"));
_symfonyContext = PhpBenchmarkShared.CreateContext(Path.Combine(fixturesBase, "symfony"));
_wordpressContext = PhpBenchmarkShared.CreateContext(Path.Combine(fixturesBase, "wordpress"));
_legacyContext = PhpBenchmarkShared.CreateContext(Path.Combine(fixturesBase, "legacy"));
_pharContext = PhpBenchmarkShared.CreateContext(Path.Combine(fixturesBase, "phar"));
_containerContext = PhpBenchmarkShared.CreateContext(Path.Combine(fixturesBase, "container"));
}
[Benchmark(Description = "Basic fixture (2 packages)")]
public async Task AnalyzeBasicAsync()
=> await _engine.AnalyzeAsync(_basicContext, CancellationToken.None).ConfigureAwait(false);
[Benchmark(Description = "Laravel extended fixture (8 packages)")]
public async Task AnalyzeLaravelExtendedAsync()
=> await _engine.AnalyzeAsync(_laravelContext, CancellationToken.None).ConfigureAwait(false);
[Benchmark(Description = "Symfony fixture (7 packages)")]
public async Task AnalyzeSymfonyAsync()
=> await _engine.AnalyzeAsync(_symfonyContext, CancellationToken.None).ConfigureAwait(false);
[Benchmark(Description = "WordPress fixture (6 packages)")]
public async Task AnalyzeWordPressAsync()
=> await _engine.AnalyzeAsync(_wordpressContext, CancellationToken.None).ConfigureAwait(false);
[Benchmark(Description = "Legacy fixture (3 packages, old autoload)")]
public async Task AnalyzeLegacyAsync()
=> await _engine.AnalyzeAsync(_legacyContext, CancellationToken.None).ConfigureAwait(false);
[Benchmark(Description = "PHAR fixture (5 packages)")]
public async Task AnalyzePharAsync()
=> await _engine.AnalyzeAsync(_pharContext, CancellationToken.None).ConfigureAwait(false);
[Benchmark(Description = "Container fixture (7 packages with extensions)")]
public async Task AnalyzeContainerAsync()
=> await _engine.AnalyzeAsync(_containerContext, CancellationToken.None).ConfigureAwait(false);
}

View File

@@ -0,0 +1,3 @@
using BenchmarkDotNet.Running;
BenchmarkRunner.Run<PhpLanguageAnalyzerBenchmark>();

View File

@@ -0,0 +1,21 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net10.0</TargetFramework>
<LangVersion>preview</LangVersion>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
<NoWarn>$(NoWarn);NU1603</NoWarn>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="BenchmarkDotNet" Version="0.14.0" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\__Libraries\StellaOps.Scanner.Analyzers.Lang\StellaOps.Scanner.Analyzers.Lang.csproj" />
<ProjectReference Include="..\..\__Libraries\StellaOps.Scanner.Analyzers.Lang.Php\StellaOps.Scanner.Analyzers.Lang.Php.csproj" />
<ProjectReference Include="..\..\__Libraries\StellaOps.Scanner.Core\StellaOps.Scanner.Core.csproj" />
</ItemGroup>
</Project>