You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

多线程场景下Interlocked.Increment隐式调用引发CPU开销问题排查

性能瓶颈排查:并发线程中隐式调用System.Threading.Interlocked.Increment的问题

我在谷歌和Stack Overflow上未找到相关问题的解答,因此在此寻求帮助。

前言

我正在开发一款对性能要求极高的应用,采用多线程将任务分配至所有处理器核心以实现最大吞吐量。有意思的是,通过批量并行处理任务,原生方式能获得更高吞吐量。无论使用通用ThreadPool还是自定义线程池,均存在相同问题。我测试过Parallel(PLINQ)和Tasks,但它们会在堆上产生内存分配开销,我希望尽可能减少此类开销以降低GC压力。


问题详情

并发线程中的函数调用会隐式调用System.Threading.Interlocked.Increment方法,在递归函数中尤其会造成巨大开销。我对应用进行了性能分析,发现每个需要隐式保护其运行栈帧的函数调用都会调用该方法——推测是为确保局部变量的线程安全。这种互锁操作似乎由主线程管理,形成了严重的性能瓶颈。

  • 性能分析截图1:标记行是该方法的内部调用位置,忽略底部的深红色线条,它们与函数的递归调用特性相关,数值过大正是由该问题导致。
  • 性能分析截图2:我可以通过内联小型函数代码来减少该方法的隐式调用,但这对递归调用无效。
  • 性能分析截图3:每次递归调用都会分支到该函数,给主线程带来明显开销。

线程初始化代码如下:

ThreadPool.UnsafeQueueUserWorkItem((l_state) =>
{
    action(l_state);

    //Other code omitted for brevity
}, state);

性能分析所指向的调用函数如下:

public void ProcessCollisions(Collider collider)
{
    var result = _tree.Query(in collider.Bounds);

    //Other code omitted for brevity
}

补充说明:我在通用ThreadPool中排队的工作项数量多于处理器核心数,这是有意为之,目的是填补线程调度间隙,更高效地利用CPU核心。每个碰撞体对应一个ThreadPool工作项,由于ThreadPool线程是长生命周期的,最终会处理所有项,队列中可能存在数万个工作项。


已尝试的方案

  • 使用自定义线程池替代通用ThreadPool:对所述问题无改善。
  • 内联函数调用:仅为临时方案,非根本解决办法,且不适用于递归调用。
  • 使用PLINQ:会产生内部堆内存分配,不符合需求。
  • 使用Tasks:会产生内部堆内存分配,不符合需求。

核心疑问

关于线程执行,我是否忽略了什么关键点?是Query_Internal函数中对_tree内部数组的共享引用与使用导致的,还是存在某种与线程同步相关的隐式运行时处理?

内容的提问来源于stack exchange,提问作者Tim Otto

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.02 02:25:16