Skip to content

Conversation

@r-Larch
Copy link

@r-Larch r-Larch commented Nov 6, 2025

Hi,

This PR brings massive performance at the cost of some breaking changes in the IConverter interface and all derived types.

Key Changes:

  • Use TextWriter to build the result Markdown
  • Use new performance APIs for text manipulation (net9.0)
  • Add polyfills to continue to support legacy target frameworks (net46, netstandard2.0, net6.0, net9.0)
  • Cover all target frameworks with tests (net471, net6.0, net9.0) except net46, as Verify.Xunit is not available for it.
  • Adding the project ReverseMarkdown.Benchmark to run benchmarks.
  • All Tests are green -> this is a refactor without changing behavior.

Note: I suggest dropping support for legacy target frameworks after the net10 release on November 11th.
Dropping legacy support basically means reverting commit b9164ce (makes the code easier to maintain)

Take a look at the benchmark below and note the speed and memory difference.
I tested:

  • 1k paragraphs
  • 10k paragraphs
  • 41k paragraphs (real-world example)

Please feel free to merge or close.
I fully understand if you don't like to introduce the breaking changes.

Kind regards
René


Comparing ReverseMarkdown v4.7.1 vs TextWriter approach

Hardware: AMD Ryzen 9 3900X 3.80GHz, 24 cores, 12 physical cores

BenchmarkDotNet v0.15.6, Windows 11 (10.0.26200.6899)
AMD Ryzen 9 3900X 3.80GHz, 1 CPU, 24 logical and 12 physical cores
.NET SDK 9.0.306
  [Host]   : .NET 9.0.10 (9.0.10, 9.0.1025.47515), X64 RyuJIT x86-64-v3
  .NET 9.0 : .NET 9.0.10 (9.0.10, 9.0.1025.47515), X64 RyuJIT x86-64-v3

Job=.NET 9.0 Runtime=.NET 9.0

Speed Memory
logarithmic scale on Y speed memory
linear scale on Y speed-linear memory-linear

Running with Files/1000-paragraphs.html file (size: 442KB) and 1000 paragraphs.

Method Mean Error StdDev Gen0 Gen1 Gen2 Allocated Ratio
ReverseMarkdown TextWriter 25.96 ms 0.519 ms 0.744 ms 3500.0000 1593.7500 1218.7500 24.95 MB 1
ReverseMarkdown v4.7.1 147.7 ms 2.95 ms 8.37 ms 100500.0000 97500.0000 97500.0000 896.35 MB 5.689

Outliers:

  • ReverseMarkdown v4.7.1: .NET 9.0 -> 2 outliers were removed (172.08 ms, 174.42 ms)

Running with Files/10k-paragraphs.html file (size: 3.7MB) and 10k paragraphs.

Method Mean Error StdDev Gen0 Gen1 Gen2 Allocated Ratio
ReverseMarkdown TextWriter 0.232 s 0.005 s 0.009 s 20000.0000 5000.0000 1000.0000 210.15 MB 1
ReverseMarkdown v4.7.1 14.08 s 0.280 s 0.747 s 624000.0000 605000.0000 603000.0000 75.27 GB 60.69

Outliers:

  • ReverseMarkdown TextWriter: .NET 9.0 -> 1 outlier was removed (265.53 ms)
  • ReverseMarkdown v4.7.1: .NET 9.0 -> 2 outliers were removed (17.04 s, 17.23 s)

Running with Files/huge.html file (size: 16MB) and 41312 paragraphs.

Method Mean Error StdDev Gen0 Gen1 Gen2 Allocated Ratio
ReverseMarkdown TextWriter 0.944 s 0.0175 s 0.0172 s 86000.0000 20000.0000 3000.0000 955.34 MB 1
ReverseMarkdown v4.7.1 191.611 s 3.7686 s 4.4863 s 2735000.0000 2666000.0000 2659000.0000 640544.94 MB 202.97

@mysticmind
Copy link
Owner

@r-Larch Appreciate you taking the time to improve performance of the lib by using text writer. But the changes are just too massive that it is going to take a quite a lot of my time for me to check through them. Anyhow, I will see if I can review by next week or so.

@r-Larch
Copy link
Author

r-Larch commented Nov 9, 2025

I see the tests are failing in GitHub actions because of nuget package version outside of dependency constraint in the test project for the targetframework net471.
I saw the warning on my machine but the tests run successfully and were green.
I will fix that soon.

@mysticmind
Copy link
Owner

mysticmind commented Nov 20, 2025

@r-Larch I am bit slow on this due to work on other OSS libs (Marten), will definitely get to it this week.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants