When documents are generated from scratch on the server, without using templates or MailMerge, small implementation details can have a measurable impact. In this type of workflow, the application creates every paragraph, heading, bullet list, table cell, and formatted text fragment programmatically. If each fragment is inserted first, selected again, and then formatted through the live selection, the document engine has to perform additional selection work for every operation. This benchmark compares two ways to create the same generated document with ServerTextControl. The first pattern creates a Selection object, sets text and formatting on that object, and assigns it once. The comparison pattern inserts text first, selects the inserted range, and then changes formatting through the live Selection. Selection Object PerformanceIn this benchmark, prebuilding TXTextControl.Selection objects is consistently about factor 2 faster than inserting text, selecting it, and formatting the live selection afterwards. The Faster Pattern: Build the Selection First The recommended pattern prepares the complete selection object before it is assigned to the current document position. Text and formatting are applied to the temporary object, and the assignment to Selection inserts the prepared content in one step. AppendPrebuilt(control, new Selection { Text = paragraph + "\r\n", FontName = "Calibri", FontSize = Twips(10) }); static void AppendPrebuilt(ServerTextControl control, Selection selection) { control.Selection = selection; } The same approach is used for headings, normal paragraphs, and bullet text. Formatting such as font name, font size, bold, and italic is applied directly to the new Selection instance before it is inserted. The Slower Pattern: Insert, Select, and Format The comparison path performs more document-selection work. It inserts the text, selects the inserted range in the live document, applies formatting to the active selection, and then moves the selection back to the end of the inserted text. int start = control.Selection.Start + control.Selection.Length; control.Selection.Text = text; control.Select(start, text.Length); control.Selection.FontName = "Calibri"; control.Selection.FontSize = Twips(10); control.Select(start + text.Length, 0); This pattern is easy to write because it resembles interactive editing. But in generated documents it repeats selection and formatting operations for every fragment. The more paragraphs, sections, and list items the document contains, the more visible this overhead becomes. Benchmark Setup The benchmark is a .NET console application using TXTextControl.TextControl.Core.SDK and ServerTextControl. Both test paths create the same logical document content. The generated document contains a title, subtitle, sections, section headings, paragraphs, and bullet lists. Each profile is warmed up before timing. The measured result is reported as average milliseconds per generated document. PDF files are written after the benchmark run so that disk I/O and PDF export do not affect the timing numbers. Two dimensions were tested separately: A static number of sections with an increasing number of paragraphs per section. A linear increase in the number of sections with a static number of paragraphs and bullets per section. Results: Static Sections, Variable Paragraphs The first test keeps the document structure stable with 10 sections and 4 bullets per section. Only the number of paragraphs per section changes from 10 to 100. Sections Paragraphs/Section Bullets/Section Elements Prebuilt ms/doc Select ms/doc Speedup 101041525.710.61.86x 102042529.216.51.80x 1030435210.621.62.04x 1040445214.229.32.06x 1050455218.237.22.04x 1060465222.246.72.10x 1070475227.256.72.09x 1080485234.768.91.99x 1090495237.385.32.29x 101004105242.988.92.08x The paragraph test shows a clear scaling trend. As the number of generated text fragments grows, both approaches take longer, but the live-selection approach grows faster. Across the test range, the prebuilt selection pattern stays close to twice as fast. Results: Variable Sections The second test keeps the content inside each section stable with 10 paragraphs and 4 bullets per section. The section count increases linearly from 2 to 20. Sections Paragraphs/Section Bullets/Section Elements Prebuilt ms/doc Select ms/doc Speedup 2104321.43.02.18x 4104622.34.62.02x 6104923.26.42.03x 81041224.48.11.85x 101041525.29.11.75x 121041825.310.41.98x 141042126.112.32.02x 161042427.214.11.95x 181042728.016.22.02x 201043029.018.32.04x This section-based test isolates document structure growth. The number of sections increases in equal steps, while the amount of content per section remains unchanged. Again, the result is consistent: prebuilt Selection objects avoid repeated live-selection operations and remain approximately twice as fast. What the Results Show The important point is not a single timing value. Timings vary by machine, runtime, and document complexity. The important result is the shape of the data. Both benchmarks show that prebuilding the Selection object scales more efficiently as the number of generated content elements increases. For applications that generate contracts, reports, invoices, statements, or other business documents, this pattern is especially useful when many formatted text fragments are inserted programmatically. Instead of thinking like an editor that inserts text and then selects it, think like a document generator: prepare the content fragment first and insert it once. Conclusion When generating documents with TX Text Control .NET Server, creating and formatting a Selection object before assigning it to control.Selection is the more efficient pattern. In this benchmark, it reduced document generation time by approximately factor 2 compared to inserting text first, selecting the inserted range, and formatting the live selection. The code change is small, but the effect is visible as documents grow. For high-volume document generation or templates with many formatted fragments, using prebuilt Selection objects is a practical optimization that keeps the code simple and improves throughput.