0

0

c# Span 和 Memory 如何提升并发性能

月夜之吻

月夜之吻

发布时间:2026-01-18 12:21:08

|

199人浏览过

|

来源于php中文网

原创

Span和Memory本身不提升并发性能,它们是为避免堆分配、减少GC压力而设计的内存访问工具,仅在短生命周期、只读或单写多读场景中间接支撑高并发。

c# span<t> 和 memory<t> 如何提升并发性能

Span 和 Memory 本身不提升并发性能

这是最关键的误判点:SpanMemory 不是并发原语,它们不带锁、不保证线程安全、也不参与调度。用错场景反而引发 System.IndexOutOfRangeExceptionObjectDisposedException(尤其在跨线程传递 Span 时)。

它们的价值在于:避免堆分配、减少 GC 压力、绕过数组边界检查(JIT 优化后),从而间接支撑高并发吞吐——前提是你的并发瓶颈真正在内存分配或拷贝上。

哪些并发场景能真正受益

典型有效场景集中在「短生命周期、高频率、只读或单线程写+多线程读」的数据处理链路中:

  • HTTP 请求体解析(如 JSON body 转 Span 后直接切片解析,不 new byte[])
  • Socket 接收缓冲区复用(Memory 持有池化 ArrayPool.Shared 分配的数组,避免每次接收都 new)
  • 高性能日志格式化(用 Span 拼接结构化字段,配合 IBufferWriter 直写到输出流)
  • 无锁队列中传递只读数据快照(Memory 可跨线程传递;Span 绝对不可)

Memory 是并发友好的唯一选择

Span 是 ref-like 类型,绑定帧或特定对象生命周期,**不能作为字段、不能存储在堆对象中、不能跨 await 边界、更不能在线程间传递**。试图这么做会触发编译错误或运行时 System.ArgumentException: Span cannot be used in this context

Memory 才是为异步/并发设计的轻量包装器,它可安全持有并传递,但需注意:

AI at Meta
AI at Meta

Facebook 旗下的AI研究平台

下载
  • 底层仍可能指向堆数组(如 new byte[1024])、栈内存(stackalloc,但无法跨方法返回)或本机内存(NativeMemory.Allocate
  • 若用 ArrayPool.Shared.Rent() 创建 Memory,必须确保归还(Return()),否则池耗尽会导致新分配退化为 new byte[]
  • 多个线程同时读同一 Memory 安全;但若某线程在写底层数组(比如通过 Memory.Span 修改),其他线程读就构成竞态——这和普通数组一样,需额外同步

真实代码中怎么写才不翻车

以下是一个 Socket 接收 + 复用缓冲区的典型模式,体现 Memory 如何降低分配压力:

private static readonly ArrayPool _pool = ArrayPool.Shared;

public async Task ProcessRequestAsync(Socket socket)
{
    var buffer = _pool.Rent(8192);
    try
    {
        var memory = new Memory(buffer);
        int bytesRead = await socket.ReceiveAsync(memory, SocketFlags.None);
        
        // ✅ 安全:只读切片,不修改 buffer 内容
        var payload = memory.Slice(0, bytesRead);
        ParseRequest(payload); // 接收端逻辑,入参为 ReadOnlySpan
    }
    finally
    {
        // ✅ 必须归还,否则池泄漏
        _pool.Return(buffer);
    }
}

注意三点:

  • 不要把 memory.Slice(...) 存成类字段或传给其他线程长期持有——Memory 不管理生命周期,只依赖你正确归还底层数组
  • 不要在 ParseRequest 内部保存 ReadOnlySpan 到字段——它会随栈帧销毁而失效
  • 如果解析过程需要异步等待(比如查数据库),必须先将关键数据拷贝出来(ToArray() 或写入目标对象),不能依赖原始 Span/Memory

真正卡并发性能的,往往不是 Span 或 Memory 用得够不够“炫”,而是有没有把它们嵌进正确的内存生命周期里——池没配对、切片越界、跨线程误传 Span,比不用它们还容易出问题。

相关文章

数码产品性能查询
数码产品性能查询

该软件包括了市面上所有手机CPU,手机跑分情况,电脑CPU,电脑产品信息等等,方便需要大家查阅数码产品最新情况,了解产品特性,能够进行对比选择最具性价比的商品。

下载

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

相关专题

更多
json数据格式
json数据格式

JSON是一种轻量级的数据交换格式。本专题为大家带来json数据格式相关文章,帮助大家解决问题。

412

2023.08.07

json是什么
json是什么

JSON是一种轻量级的数据交换格式,具有简洁、易读、跨平台和语言的特点,JSON数据是通过键值对的方式进行组织,其中键是字符串,值可以是字符串、数值、布尔值、数组、对象或者null,在Web开发、数据交换和配置文件等方面得到广泛应用。本专题为大家提供json相关的文章、下载、课程内容,供大家免费下载体验。

533

2023.08.23

jquery怎么操作json
jquery怎么操作json

操作的方法有:1、“$.parseJSON(jsonString)”2、“$.getJSON(url, data, success)”;3、“$.each(obj, callback)”;4、“$.ajax()”。更多jquery怎么操作json的详细内容,可以访问本专题下面的文章。

310

2023.10.13

go语言处理json数据方法
go语言处理json数据方法

本专题整合了go语言中处理json数据方法,阅读专题下面的文章了解更多详细内容。

74

2025.09.10

堆和栈的区别
堆和栈的区别

堆和栈的区别:1、内存分配方式不同;2、大小不同;3、数据访问方式不同;4、数据的生命周期。本专题为大家提供堆和栈的区别的相关的文章、下载、课程内容,供大家免费下载体验。

391

2023.07.18

堆和栈区别
堆和栈区别

堆(Heap)和栈(Stack)是计算机中两种常见的内存分配机制。它们在内存管理的方式、分配方式以及使用场景上有很大的区别。本文将详细介绍堆和栈的特点、区别以及各自的使用场景。php中文网给大家带来了相关的教程以及文章欢迎大家前来学习阅读。

572

2023.08.10

堆和栈的区别
堆和栈的区别

堆和栈的区别:1、内存分配方式不同;2、大小不同;3、数据访问方式不同;4、数据的生命周期。本专题为大家提供堆和栈的区别的相关的文章、下载、课程内容,供大家免费下载体验。

391

2023.07.18

堆和栈区别
堆和栈区别

堆(Heap)和栈(Stack)是计算机中两种常见的内存分配机制。它们在内存管理的方式、分配方式以及使用场景上有很大的区别。本文将详细介绍堆和栈的特点、区别以及各自的使用场景。php中文网给大家带来了相关的教程以及文章欢迎大家前来学习阅读。

572

2023.08.10

高德地图升级方法汇总
高德地图升级方法汇总

本专题整合了高德地图升级相关教程,阅读专题下面的文章了解更多详细内容。

71

2026.01.16

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
WEB前端教程【HTML5+CSS3+JS】
WEB前端教程【HTML5+CSS3+JS】

共101课时 | 8.3万人学习

JS进阶与BootStrap学习
JS进阶与BootStrap学习

共39课时 | 3.2万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号