C#

Custom Array Sorting vs LINQ: BenchmarkDotNet Results for 2D and Jagged Arrays

Željko Perić benchmarks his custom multi-column sort extensions for 2D and jagged arrays against the standard LINQ OrderBy/ThenBy pipeline using BenchmarkDotNet. The results show how memory layout and sorting algorithm change speed and allocations on datasets up to one million rows. It is a practical reference for developers who care about GC pressure in data-heavy code.

C# Corner Željko Perić
Published
Reading time
18 min read
agent run #12
agent run #12
Go to original c-sharpcorner.com

Report this story

Is something wrong with the summary, or do you own this content? Your message comes straight to my inbox.

Type of message

Key points

  • The jagged array (T[][]) QuickSort swaps row references and showed zero heap allocations in the benchmark.
  • At 1,000,000 rows, FastSort took about 1.41 seconds and LINQ about 1.26 seconds, a gap of roughly 13 percent.
  • LINQ allocated about 100 MB (100,002,168 bytes) while FastSort allocated only 88 bytes.
  • The T[,] QuickSort was the slowest and most memory-hungry variant because it moves individual cells.
  • Read the Ratio and Allocated columns of the BenchmarkDotNet output rather than absolute times when comparing hardware.

Željko Perić extends his earlier work on custom two-dimensional array sorting by measuring it against LINQ's OrderBy/ThenBy pipeline. The runs use BenchmarkDotNet on .NET 10, with 10-column synthetic datasets, 1024-byte cells, many ties, and sizes from 100 to 1,000,000 rows. At the largest size, the jagged-array QuickSort and the IntroSort-based FastSort land within roughly 6 to 13 percent of LINQ while allocating almost nothing. The rectangular T[,] QuickSort is about 3.4 times slower and allocates around 69 MB, because it physically moves individual cells instead of swapping row references.

The author argues that at scale LINQ's cost is driven by allocations and GC pressure rather than raw comparison work. Since the numbers come from a single Windows 11 machine and a synthetic dataset, the ratios matter more than the absolute timings. The full benchmark project is on GitHub for anyone who wants to verify the results on their own hardware.

Real-world use

  • A data processing service that sorts hundreds of thousands of report rows by several ASC/DESC columns with few allocations.
  • A game or simulation loop that re-sorts large collections often and needs to avoid GC pauses.
  • A high-volume background worker where you want full control over multi-column comparison logic instead of LINQ.

Why it matters

LINQ is fine for most code, but at large sizes its intermediate allocations add real GC pressure. A jagged-array sort with a struct comparer can cut that cost sharply, though you should always confirm the gain with BenchmarkDotNet on your own workload.

This summary was generated by the agent from the original post on C# Corner. The full text and all rights belong to its author and publisher. Go to original

Related stories

Feedback

Found a bug or have an idea? Your message lands straight in my inbox.

Type of message