Skip to content

Instantly share code, notes, and snippets.

@pmbanugo
Created September 22, 2025 15:50
Show Gist options
  • Select an option

  • Save pmbanugo/893e98b2ab819a219774916219ba4e9a to your computer and use it in GitHub Desktop.

Select an option

Save pmbanugo/893e98b2ab819a219774916219ba4e9a to your computer and use it in GitHub Desktop.
High-performance systems and algorithms (reasons for C# & .NET)

Great question โ€” C# has grown a lot in the last decade, and there are several features in the language and ecosystem that make it very capable for building high-performance systems while still being relatively high-level compared to C or Rust. Letโ€™s break it down by categories of features relevant to algorithms, data flows, and concurrency:


๐Ÿ”น Memory & Data Structures

struct and readonly struct

  • Value types allocated on the stack (or inline in arrays/fields).
  • Avoid GC overhead compared to reference types.
  • readonly struct ensures immutability and allows some optimizations.
  • Best for small, frequently created types (e.g., points, vectors, small state containers).

record struct

  • Combines immutability and value semantics with concise syntax.
  • Auto-generated equality and with expressions.
  • Useful when you want immutable value objects that are frequently copied (e.g., messages in pipelines).

Span<T> and Memory<T>

  • Span<T>: stack-only view over contiguous memory (arrays, slices, native buffers).
  • Avoids allocations when slicing/sub-arrays.
  • Allows safe access to unmanaged memory.
  • ReadOnlySpan<T> for read-only cases.
  • Memory<T>: heap-based version of Span<T> that can be stored and used async.

๐Ÿ‘‰ These are game changers for performance-sensitive code like parsers, protocol handlers, or data processing pipelines.

stackalloc

  • Allocate memory on the stack for short-lived buffers.
  • Great for avoiding heap allocations in hot paths (e.g., formatting numbers).

๐Ÿ”น Concurrency & Asynchrony

async / await

  • Structured, language-level async/await for I/O.
  • Avoids callback hell and integrates with the Task-based async model.
  • Perfect for I/O-bound concurrency (network, file I/O, DB calls).
  • ValueTask is available to reduce allocations in high-frequency async APIs.

Channels and Pipelines

  • System.Threading.Channels: bounded/unbounded channels for producer-consumer scenarios.
  • System.IO.Pipelines: highly optimized for streaming data (used in Kestrel, ASP.NET Core web server).
  • Great for building flow-based, high-throughput systems.

Actors via Akka.NET

  • Actor model for concurrency and distribution.
  • Encapsulates state inside actors, messaging replaces locks.
  • Good for large, distributed, message-driven systems (similar to Erlang/Scala Akka).

๐Ÿ”น Parallelism & Performance

PLINQ and TPL

  • Parallel LINQ (AsParallel) for data-parallel algorithms.
  • Task Parallel Library (Parallel.For, Task.Run) for CPU-bound workloads.

SIMD / Hardware Intrinsics

  • System.Numerics.Vector<T>: cross-platform SIMD acceleration.
  • System.Runtime.Intrinsics: fine-grained hardware intrinsics (AVX, SSE, ARM Neon).
  • Enables hand-tuned numeric algorithms.

๐Ÿ”น Advanced Features

Pattern Matching

  • Enables writing expressive and efficient state/flow logic.
  • Works nicely with records for discriminated unionโ€“like patterns.

ref struct, ref return, ref readonly

  • Allow passing data by reference without allocations.
  • ref struct like Span<T> can only live on the stack, which ensures safety.

Source Generators

  • Generate boilerplate code at compile-time (serialization, mapping, DI, etc.).
  • Avoids runtime reflection overhead.

Native Interop

  • unsafe code with pointers when you absolutely need full control.
  • DllImport / NativeAOT / CsWinRT to interop with native code at low overhead.

๐Ÿ”น Putting It Together

If youโ€™re building a high-performance system in C#, you might combine these like so:

  • Low-level processing โ†’ Span<T>, Memory<T>, SIMD intrinsics.
  • Concurrent flows โ†’ Channels or Akka.NET actors depending on scale.
  • Async I/O โ†’ async/await with ValueTask and pipelines.
  • Immutable messages โ†’ record struct.
  • Hot-path structs โ†’ readonly struct to minimize GC.
  • High throughput networking โ†’ System.IO.Pipelines with pooled buffers.

๐Ÿ‘‰ So the choice depends on your workload:

  • Compute heavy โ†’ structs, SIMD, intrinsics, PLINQ.
  • I/O heavy โ†’ async/await, pipelines, channels.
  • Distributed/messaging โ†’ Akka.NET actors, records for immutable messages.

Would you like me to map these features to concrete design patterns (e.g., message-passing, dataflow, lock-free algorithms) so you see how theyโ€™re applied in real system architecture?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment