C# Span和Memory是什么 – 高性能内存操作的利器

Span和Memory是C# 7.2引入的高性能内存抽象,Span为上安全的内存视图,零开销操作连续内存;Memory可跨作用域使用,支持async和字段存储,配合MemoryPool实现零拷贝与缓冲复用,显著降低GC压力,适用于高频数据处理场景。

C# Span和Memory是什么 – 高性能内存操作的利器

SpanMemory 是 C# 7.2 引入的高性能内存抽象类型,专为减少内存分配、避免复制、提升性能而设计,尤其适合底层操作、高频数据处理和零拷贝场景。

Span上安全的“内存视图”

Span 是一个轻量级、仅栈分配(stack-only)的结构体,它不拥有数据,只指向一段连续内存(如数组、栈内存、非托管内存),并携带长度信息。它的关键特性是不能逃逸到堆上(比如不能作为字段、不能被 async 方法捕获),因此编译器能严格保证其生命周期安全。

  • 支持从 T[]、String、stackalloc T[]、非托管指针等创建
  • 切片(Slice)、索引、遍历都零开销,不产生新分配
  • 常见用途:解析字节流、字符串切片、高性能序列化/反序列化
  • 示例:Span data = stackalloc byte[256]; data.Slice(0, 128);

Memory:可跨作用域的“托管内存视图”

Memory 是 Span 的“可逃逸”兄弟,可以安全地作为字段、参数、返回值甚至用于 async 方法中。它内部包装了 Span 或其他内存源(如数组、ArraySegment),通过 MemoryManager 抽象统一管理生命周期。

  • 比 Span 稍重(有虚方法调用开销),但保留了大部分零分配优势
  • 配合 ReadOnlyMemory 使用更安全,防止意外写入
  • 典型场景:ASP.net Core 中的 Request.Body.ReadAsync 接收 Memory,Kestrel 直接复用缓冲池

为什么它们能提升性能?

传统方式(如 string.Substring、Array.copy)常触发堆分配或数据复制,而 Span/Memory 让你直接操作原始内存块:

C# Span和Memory是什么 – 高性能内存操作的利器

Jaaz

开源的AI设计智能体

C# Span和Memory是什么 – 高性能内存操作的利器 216

查看详情 C# Span和Memory是什么 – 高性能内存操作的利器

  • 避免不必要的数组分配(比如临时子串、中间 byte[])
  • 绕过 GC 压力,尤其在高吞吐服务中效果显著
  • System.Buffers.MemoryPool 配合,实现高效缓冲区复用
  • 支持 unsafe 操作(如指针转换),又保持类型安全边界

使用注意点

它们强大但需理解约束:

  • Span 不能存储在堆对象中(编译器会报错),async 方法里慎用(推荐转 Memory
  • Memory 不一定对应托管数组——可能是 native 内存或池化内存,释放需按来源处理
  • 线程传递需确保内存生命周期足够长,否则可能悬空
  • 并非万能:简单逻辑用 string 或 List 更清晰,过度优化反而增加复杂度

基本上就这些。Span 和 Memory 不是语法糖,而是运行时与语言协同设计的底层能力,用对地方,性能提升立竿见影。

上一篇
下一篇
text=ZqhQzanResources