diff --git a/README.md b/README.md
index 431b3aa8..4ecccc76 100644
--- a/README.md
+++ b/README.md
@@ -79,6 +79,20 @@ The main idea behind AngleSharp.Css is to expose the CSSOM as it would be in the
- Calculated values (i.e., `calc(20px + 50%)`)
- Window-based declaration calculations, see `window.GetComputedStyle`
+## Benchmarks
+
+The `AngleSharp.Performance.Css` project uses [BenchmarkDotNet](https://benchmarkdotnet.org/) to compare CSS parsing performance across libraries. Run the benchmarks in Release mode:
+
+```bash
+dotnet run --project src/AngleSharp.Performance.Css/AngleSharp.Performance.Css.csproj -c Release --framework net10.0
+```
+
+To run a quick smoke test instead of a full benchmark:
+
+```bash
+dotnet run --project src/AngleSharp.Performance.Css/AngleSharp.Performance.Css.csproj -c Release --framework net10.0 -- --job short
+```
+
## Participating
Participation in the project is highly welcome. For this project the same rules as for the AngleSharp core project may be applied.
diff --git a/src/AngleSharp.Performance.Css/AngleSharp.Performance.Css.csproj b/src/AngleSharp.Performance.Css/AngleSharp.Performance.Css.csproj
index e48c8dde..0891ee5c 100644
--- a/src/AngleSharp.Performance.Css/AngleSharp.Performance.Css.csproj
+++ b/src/AngleSharp.Performance.Css/AngleSharp.Performance.Css.csproj
@@ -1,14 +1,8 @@
- net10.0
-
+ net472;net10.0
Exe
-
- false
- default
-
-
- AnyCPU
+ 9
@@ -18,16 +12,18 @@
-
-
netstandard2.0
-
-
+
+
+
+
+
+
-
\ No newline at end of file
+
diff --git a/src/AngleSharp.Performance.Css/AngleSharpParser.cs b/src/AngleSharp.Performance.Css/AngleSharpParser.cs
deleted file mode 100644
index b1b30ded..00000000
--- a/src/AngleSharp.Performance.Css/AngleSharpParser.cs
+++ /dev/null
@@ -1,26 +0,0 @@
-namespace AngleSharp.Performance.Css
-{
- using AngleSharp;
- using AngleSharp.Css.Parser;
- using System;
-
- class AngleSharpParser : ITestee
- {
- private static readonly CssParserOptions options = new CssParserOptions
- {
- IsIncludingUnknownDeclarations = true,
- IsIncludingUnknownRules = true,
- IsToleratingInvalidSelectors = true,
- };
- private static readonly CssParser parser = new CssParser(options);
-
- public String Name => "AngleSharp";
-
- public Type Library => typeof(BrowsingContext);
-
- public void Run(String source)
- {
- parser.ParseStyleSheet(source);
- }
- }
-}
diff --git a/src/AngleSharp.Performance.Css/CsCssParser.cs b/src/AngleSharp.Performance.Css/CsCssParser.cs
deleted file mode 100644
index 915051e0..00000000
--- a/src/AngleSharp.Performance.Css/CsCssParser.cs
+++ /dev/null
@@ -1,26 +0,0 @@
-namespace AngleSharp.Performance.Css
-{
- using Alba.CsCss.Style;
- using System;
-
- class CsCssParser : ITestee
- {
- public String Name => "CsCss";
-
- public Type Library => typeof(CssLoader);
-
- public void Run(String source)
- {
- var parser = new CssLoader { Compatibility = Alba.CsCss.BrowserCompatibility.FullStandards };
-
- try
- {
- parser.ParseSheet(source, new Uri("http://localhost/foo.css"), new Uri("http://localhost"));
- }
- catch
- {
- // May crash otherwise if invalid input detected ...
- }
- }
- }
-}
diff --git a/src/AngleSharp.Performance.Css/CssParserBenchmarks.cs b/src/AngleSharp.Performance.Css/CssParserBenchmarks.cs
new file mode 100644
index 00000000..771cb0a4
--- /dev/null
+++ b/src/AngleSharp.Performance.Css/CssParserBenchmarks.cs
@@ -0,0 +1,77 @@
+namespace AngleSharp.Performance.Css
+{
+ using AngleSharp.Css.Parser;
+ using BenchmarkDotNet.Attributes;
+ using ExCSS;
+ using System;
+ using System.Collections.Generic;
+ using System.IO;
+ using System.Linq;
+
+ [MemoryDiagnoser]
+ public class CssParserBenchmarks
+ {
+ private static readonly CssParserOptions AngleSharpOptions = new CssParserOptions
+ {
+ IsIncludingUnknownDeclarations = true,
+ IsIncludingUnknownRules = true,
+ IsToleratingInvalidSelectors = true,
+ };
+
+ private static readonly CssParser AngleSharpParser = new CssParser(AngleSharpOptions);
+
+ private string _source = null!;
+
+ [ParamsSource(nameof(CssFileNames))]
+ public string CssFileName { get; set; } = null!;
+
+ public static IEnumerable CssFileNames()
+ {
+ var dir = Path.Combine(AppContext.BaseDirectory, "Samples");
+
+ return Directory.GetFiles(dir, "*.css")
+ .OrderBy(f => f)
+ .Select(f => Path.GetFileNameWithoutExtension(f));
+ }
+
+ [GlobalSetup]
+ public void Setup()
+ {
+ var path = Path.Combine(AppContext.BaseDirectory, "Samples", CssFileName + ".css");
+ _source = File.ReadAllText(path);
+ }
+
+ [Benchmark(Baseline = true)]
+ public object AngleSharp()
+ {
+ return AngleSharpParser.ParseStyleSheet(_source);
+ }
+
+ [Benchmark]
+ public object ExCss()
+ {
+ var parser = new StylesheetParser();
+ return parser.Parse(_source);
+ }
+
+#if NET472
+ [Benchmark]
+ public object CsCss()
+ {
+ var parser = new Alba.CsCss.Style.CssLoader
+ {
+ Compatibility = Alba.CsCss.BrowserCompatibility.FullStandards
+ };
+
+ try
+ {
+ return parser.ParseSheet(_source, new Uri("http://localhost/foo.css"), new Uri("http://localhost"));
+ }
+ catch
+ {
+ return null!;
+ }
+ }
+#endif
+ }
+}
diff --git a/src/AngleSharp.Performance.Css/ExCssParser.cs b/src/AngleSharp.Performance.Css/ExCssParser.cs
deleted file mode 100644
index e389aa8c..00000000
--- a/src/AngleSharp.Performance.Css/ExCssParser.cs
+++ /dev/null
@@ -1,18 +0,0 @@
-namespace AngleSharp.Performance.Css
-{
- using System;
- using ExCSS;
-
- class ExCssParser : ITestee
- {
- public String Name => "ExCSS";
-
- public Type Library => typeof(Parser);
-
- public void Run(String source)
- {
- var parser = new Parser();
- parser.Parse(source);
- }
- }
-}
diff --git a/src/AngleSharp.Performance.Css/Program.cs b/src/AngleSharp.Performance.Css/Program.cs
index 27571603..7dde577c 100644
--- a/src/AngleSharp.Performance.Css/Program.cs
+++ b/src/AngleSharp.Performance.Css/Program.cs
@@ -1,31 +1,12 @@
namespace AngleSharp.Performance.Css
{
- using System;
- using System.Collections.Generic;
- using System.IO;
+ using BenchmarkDotNet.Running;
class Program
{
- static void Main(String[] args)
+ static void Main(string[] args)
{
- var samplesDir = Path.Combine(AppContext.BaseDirectory, "Samples");
- var stylesheets = new FileTests()
- .IncludeFromDirectory(samplesDir);
-
- var parsers = new List
- {
- new AngleSharpParser(),
- new ExCssParser(),
- new CsCssParser(),
- };
-
- var testsuite = new TestSuite(parsers, stylesheets.Tests, new Output(), new Warmup())
- {
- NumberOfRepeats = 5,
- NumberOfReRuns = 1,
- };
-
- testsuite.Run();
+ BenchmarkRunner.Run(args: args);
}
}
}