From aa2243bad97b755171dd3cadf7a09b7dd0cd7967 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Sun, 2 Aug 2026 15:44:07 +0000 Subject: [PATCH] perf: HtmlParser reuses CurrentTag and Content StringBuilders across tokens Instead of allocating a new { Contents = StringBuilder() } on every EmitTag, EmitSelfClosingTag, EmitToAttributeValue, and Emit call, reuse the existing CharList by calling .Clear(). This eliminates two StringBuilder allocations per HTML element (one for CurrentTag, one for Content) - for a typical HTML document with hundreds of elements this removes hundreds of short-lived heap objects. The CharList.Clear() method already existed for this purpose. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- src/FSharp.Data.Html.Core/HtmlParser.fs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/FSharp.Data.Html.Core/HtmlParser.fs b/src/FSharp.Data.Html.Core/HtmlParser.fs index 2940216ea..af6ce78f3 100644 --- a/src/FSharp.Data.Html.Core/HtmlParser.fs +++ b/src/FSharp.Data.Html.Core/HtmlParser.fs @@ -171,7 +171,7 @@ module internal HtmlParser = member x.EmitSelfClosingTag() = let name = x.CurrentTag.ToString().Trim() let result = Tag(true, name, x.GetAttributes()) - x.CurrentTag <- { Contents = StringBuilder() } + x.CurrentTag.Clear() x.InsertionMode <- DefaultMode x.Attributes <- [] x.Tokens <- result :: x.Tokens @@ -217,7 +217,7 @@ module internal HtmlParser = else DefaultMode - x.CurrentTag <- { Contents = StringBuilder() } + x.CurrentTag.Clear() x.Attributes <- [] x.Tokens <- result :: x.Tokens @@ -228,7 +228,7 @@ module internal HtmlParser = for c in content do x.ConsAttrValue c - x.Content <- { Contents = StringBuilder() } + x.Content.Clear() x.InsertionMode <- DefaultMode member x.Emit() : unit = @@ -252,7 +252,7 @@ module internal HtmlParser = | DocTypeMode -> DocType content | CDATAMode -> CData(content.Replace("", "")) - x.Content <- { Contents = StringBuilder() } + x.Content.Clear() x.InsertionMode <- DefaultMode match result with