using System.Collections.Generic;
using System.Diagnostics;
using System.Text.RegularExpressions;
private static readonly string[] TestStrings = new string[]
"<div>Simple div tag</div>",
"<p>Paragraph <strong>with</strong> <em>formatting</em></p>",
"<div class=\"test\" id='sample'>Element with attributes</div>",
"<h1>Title</h1><p>Content with <a href=\"https://example.com\">link</a></p>",
"<ul><li>Item 1</li><li>Item 2</li><li>Item 3</li></ul>",
"<table><tr><th>Header</th></tr><tr><td>Data</td></tr></table>"
public static void Main()
const int iterations = 100000;
const int warmupIterations = 1000;
Console.WriteLine("Performing warmup...");
for (int i = 0; i < warmupIterations; i++)
foreach (var str in TestStrings)
RemoveHTMLFromStr_Optimized1(str);
RemoveHTMLFromStr_Optimized2(str);
RemoveHTMLFromStr_Optimized3(str);
Console.WriteLine("Starting benchmark...\n");
ValidateImplementations();
var results1 = BenchmarkMethod("Original", iterations, () => ProcessAllStrings(RemoveHTMLFromStr));
var results2 = BenchmarkMethod("Optimized1", iterations, () => ProcessAllStrings(RemoveHTMLFromStr_Optimized1));
var results3 = BenchmarkMethod("Optimized2", iterations, () => ProcessAllStrings(RemoveHTMLFromStr_Optimized2));
var results4 = BenchmarkMethod("Optimized3", iterations, () => ProcessAllStrings(RemoveHTMLFromStr_Optimized3));
var allResults = new List<(string Name, BenchmarkResult Result)>
("Optimized1", results2),
("Optimized2", results3),
Console.WriteLine("\n=== Performance Summary ===");
Console.WriteLine("{0,-15} {1,-15} {2,-15} {3,-15} {4,-15}",
"Method", "Avg (ms)", "Min (ms)", "Max (ms)", "Memory (KB)");
Console.WriteLine(new string('-', 75));
foreach (var result in allResults)
Console.WriteLine("{0,-15} {1,-15:F2} {2,-15:F2} {3,-15:F2} {4,-15:F2}",
result.Result.MemoryUsed / 1024.0);
var rankedBySpeed = allResults.OrderBy(r => r.Result.Average).ToList();
var fastestMethod = rankedBySpeed.First();
Console.WriteLine("\n=== Rankings ===");
Console.WriteLine("By Speed:");
for (int i = 0; i < rankedBySpeed.Count; i++)
var item = rankedBySpeed[i];
double percentDiff = i == 0 ? 0 :
((item.Result.Average - fastestMethod.Result.Average) / fastestMethod.Result.Average * 100);
Console.WriteLine($"{i + 1}. {item.Name} - {item.Result.Average:F2}ms " +
(i == 0 ? "(fastest)" : $"(+{percentDiff:F2}% slower)"));
var rankedByMemory = allResults.OrderBy(r => r.Result.MemoryUsed).ToList();
var lowestMemoryMethod = rankedByMemory.First();
Console.WriteLine("\nBy Memory Usage:");
for (int i = 0; i < rankedByMemory.Count; i++)
var item = rankedByMemory[i];
double percentDiff = i == 0 ? 0 :
((item.Result.MemoryUsed - lowestMemoryMethod.Result.MemoryUsed) / lowestMemoryMethod.Result.MemoryUsed * 100);
Console.WriteLine($"{i + 1}. {item.Name} - {item.Result.MemoryUsed / 1024.0:F2}KB " +
(i == 0 ? "(lowest)" : $"(+{percentDiff:F2}% more)"));
private static void ValidateImplementations()
Console.WriteLine("Validating all implementations produce the same output...");
foreach (var str in TestStrings)
var original = RemoveHTMLFromStr(str);
var opt1 = RemoveHTMLFromStr_Optimized1(str);
var opt2 = RemoveHTMLFromStr_Optimized2(str);
var opt3 = RemoveHTMLFromStr_Optimized3(str);
if (original != opt1 || original != opt2 || original != opt3)
Console.WriteLine($"Implementations produce different results for: {str}");
Console.WriteLine($"Original: '{original}'");
Console.WriteLine($"Optimized1: '{opt1}'");
Console.WriteLine($"Optimized2: '{opt2}'");
Console.WriteLine($"Optimized3: '{opt3}'");
Console.WriteLine("All implementations produce identical output.\n");
private static string[] ProcessAllStrings(Func<string, string> processor)
var results = new string[TestStrings.Length];
for (int i = 0; i < TestStrings.Length; i++)
results[i] = processor(TestStrings[i]);
private static readonly Regex HTMLPattern = new Regex("<(\"[^\"]*\"|'[^']*'|[^'\">])*>", RegexOptions.Compiled | RegexOptions.CultureInvariant);
public static string RemoveHTMLFromStr(string Value)
return HTMLPattern.Replace(Value, string.Empty);
private static readonly Regex simpleHTMLPattern = new Regex("<[^>]*>", RegexOptions.Compiled | RegexOptions.CultureInvariant);
public static string RemoveHTMLFromStr_Optimized1(string Value)
return simpleHTMLPattern.Replace(Value, string.Empty);
public static string RemoveHTMLFromStr_Optimized2(string Value)
if (string.IsNullOrEmpty(Value) || Value.IndexOf('<') == -1)
StringBuilder result = new StringBuilder(Value.Length);
for (int i = 0; i < Value.Length; i++)
return result.ToString();
public static string RemoveHTMLFromStr_Optimized3(string Value)
if (string.IsNullOrEmpty(Value) || Value.IndexOf('<') == -1)
char[] buffer = new char[Value.Length];
ReadOnlySpan<char> span = Value.AsSpan();
for (int i = 0; i < span.Length; i++)
buffer[writeIndex++] = c;
return new string(buffer, 0, writeIndex);
private class BenchmarkResult
public double Average { get; set; }
public double Min { get; set; }
public double Max { get; set; }
public long MemoryUsed { get; set; }
private static BenchmarkResult BenchmarkMethod(
var times = new double[trials];
for (int trial = 0; trial < trials; trial++)
GC.WaitForPendingFinalizers();
long memoryBefore = GC.GetTotalMemory(true);
var sw = Stopwatch.StartNew();
for (int i = 0; i < iterations; i++)
long memoryAfter = GC.GetTotalMemory(false);
long trialMemory = memoryAfter - memoryBefore;
if (trial > 0 && trial < trials - 1)
memoryUsed += trialMemory;
times[trial] = sw.ElapsedMilliseconds;
Console.WriteLine($"{name} Trial {trial + 1}: {times[trial]:F2}ms, Memory: {trialMemory / 1024.0:F2}KB");
return new BenchmarkResult
Average = times.Average(),
MemoryUsed = memoryUsed / (trials - 2)