# Speed Up Document Generation by Factor 2 Using Selection Objects in .NET C#

> This article compares two ServerTextControl document generation patterns: Assigning prebuilt Selection objects and formatting text after inserting and selecting it. The benchmark shows an approximately 2x performance improvement when using Selection objects.

- **Author:** Bjoern Meyer
- **Published:** 2026-07-17
- **Modified:** 2026-07-17
- **Description:** This article compares two ServerTextControl document generation patterns: Assigning prebuilt Selection objects and formatting text after inserting and selecting it. The benchmark shows an approximately 2x performance improvement when using Selection objects.
- **5 min read** (914 words)
- **Tags:**
  - .NET
  - C#
  - Performance
  - Selection
  - ServerTextControl
- **Web URL:** https://www.textcontrol.com/blog/2026/07/17/speed-up-document-generation-selection-objects-dotnet-csharp/
- **LLMs URL:** https://www.textcontrol.com/blog/2026/07/17/speed-up-document-generation-selection-objects-dotnet-csharp/llms.txt
- **LLMs-Full URL:** https://www.textcontrol.com/blog/2026/07/17/speed-up-document-generation-selection-objects-dotnet-csharp/llms-full.txt

---

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 Performance**
> 
> In 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 |
|---|---|---|---|---|---|---|
| 10 | 10 | 4 | 152 | 5.7 | 10.6 | 1.86x |
| 10 | 20 | 4 | 252 | 9.2 | 16.5 | 1.80x |
| 10 | 30 | 4 | 352 | 10.6 | 21.6 | 2.04x |
| 10 | 40 | 4 | 452 | 14.2 | 29.3 | 2.06x |
| 10 | 50 | 4 | 552 | 18.2 | 37.2 | 2.04x |
| 10 | 60 | 4 | 652 | 22.2 | 46.7 | 2.10x |
| 10 | 70 | 4 | 752 | 27.2 | 56.7 | 2.09x |
| 10 | 80 | 4 | 852 | 34.7 | 68.9 | 1.99x |
| 10 | 90 | 4 | 952 | 37.3 | 85.3 | 2.29x |
| 10 | 100 | 4 | 1052 | 42.9 | 88.9 | 2.08x |

![Document generation performance by paragraph count](https://s1-www.textcontrol.com/assets/dist/blog/2026/07/17/a/assets/performance-by-paragraphs.svg "Document generation performance by paragraph count")

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 |
|---|---|---|---|---|---|---|
| 2 | 10 | 4 | 32 | 1.4 | 3.0 | 2.18x |
| 4 | 10 | 4 | 62 | 2.3 | 4.6 | 2.02x |
| 6 | 10 | 4 | 92 | 3.2 | 6.4 | 2.03x |
| 8 | 10 | 4 | 122 | 4.4 | 8.1 | 1.85x |
| 10 | 10 | 4 | 152 | 5.2 | 9.1 | 1.75x |
| 12 | 10 | 4 | 182 | 5.3 | 10.4 | 1.98x |
| 14 | 10 | 4 | 212 | 6.1 | 12.3 | 2.02x |
| 16 | 10 | 4 | 242 | 7.2 | 14.1 | 1.95x |
| 18 | 10 | 4 | 272 | 8.0 | 16.2 | 2.02x |
| 20 | 10 | 4 | 302 | 9.0 | 18.3 | 2.04x |

![Document generation performance by section count](https://s1-www.textcontrol.com/assets/dist/blog/2026/07/17/a/assets/performance-by-sections.svg "Document generation performance by section count")

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.

---

## About Bjoern Meyer

As CEO, Bjoern is the visionary behind our strategic direction and business development, bridging the gap between our customers and engineering teams. His deep passion for coding and web technologies drives the creation of innovative products. If you're at a tech conference, be sure to stop by our booth - you'll most likely meet Bjoern in person. With an advanced graduate degree (Dipl. Inf.) in Computer Science, specializing in AI, from the University of Bremen, Bjoern brings significant expertise to his role. In his spare time, Bjoern enjoys running, paragliding, mountain biking, and playing the piano.

- [LinkedIn](https://www.linkedin.com/in/bjoernmeyer/)
- [X](https://x.com/txbjoern)
- [GitHub](https://github.com/bjoerntx)
