我目前正在开发一个性能非常关键的程序,我决定探索一条可能有助于减少资源消耗的途径,那就是增加工作线程的堆栈大小,以便将我将要访问的大部分数据(float[])移动到堆栈上(使用stackalloc).

我有read,线程的默认堆栈大小是1MB,所以为了移动所有的float[],我必须将堆栈扩展大约50倍(到50MB~).

我知道这通常被认为是"不安全的",不推荐使用,但在对照这种方法对我当前的代码进行基准测试后,我发现处理速度提高了530%!因此,我不能在没有进一步调查的情况下简单地通过这个选项,这就引出了我的问题;将烟囱增加到如此大的尺寸会有什么危险(可能会出现什么问题),我应该采取什么预防措施来尽量减少这种危险?

我的测试代码,

public static unsafe void TestMethod1()
{
    float* samples = stackalloc float[12500000];

    for (var ii = 0; ii < 12500000; ii++)
    {
        samples[ii] = 32768;
    }
}

public static void TestMethod2()
{
    var samples = new float[12500000];

    for (var i = 0; i < 12500000; i++)
    {
        samples[i] = 32768;
    }
}

推荐答案

在将测试代码与Sam进行比较后,我确定我们都是对的

  • 访问内存(读写)在任何地方都是just as fast—堆栈、全局或堆.
  • 然而,它在堆栈上速度最快,在堆上速度最慢.

它是这样的:stack<;global<;heap.(分配时间)

不过,我强烈建议大家在这件事上要小心

  1. 当您需要频繁创建从不leave函数的数组时(例如,通过传递其引用),使用堆栈将是一个巨大的改进.
  2. 如果你能回收一个数组,那就尽可能地回收!堆是长期存储对象的最佳场所.(污染全局内存不好;堆栈帧可能会消失)

(Note:1.仅适用于值类型;引用类型将在堆上分配,并且好处将减少到0)

回答问题本身:我在任何大型堆栈测试中都没有遇到任何问题

The section below is my initial answer. It is wrong-ish and the tests aren't correct. It is kept only for reference.


我的测试表明,堆栈分配的内存和全局内存在数组中的使用速度至少比堆分配的内存慢15%(需要120%的时间)!

This is my test code,以下是示例输出:

Stack-allocated array time: 00:00:00.2224429
Globally-allocated array time: 00:00:00.2206767
Heap-allocated array time: 00:00:00.1842670
------------------------------------------
Fastest: Heap.

  |    S    |    G    |    H    |
--+---------+---------+---------+
S |    -    | 100.80 %| 120.72 %|
--+---------+---------+---------+
G |  99.21 %|    -    | 119.76 %|
--+---------+---------+---------+
H |  82.84 %|  83.50 %|    -    |
--+---------+---------+---------+
Rates are calculated by dividing the row's value to the column's.

我在Windows 8.1 Pro(带更新1)上测试,使用的是i7 4700 MQ,在.NET 4.5.1下
我使用x86和x64进行了测试,结果是相同的.

Edit:我将所有线程的堆栈大小增加到201MB,样本大小增加到5000万,并将迭代次数减少到5次

Stack-allocated array time: 00:00:00.4504903
Globally-allocated array time: 00:00:00.4020328
Heap-allocated array time: 00:00:00.3439016
------------------------------------------
Fastest: Heap.

  |    S    |    G    |    H    |
--+---------+---------+---------+
S |    -    | 112.05 %| 130.99 %|
--+---------+---------+---------+
G |  89.24 %|    -    | 116.90 %|
--+---------+---------+---------+
H |  76.34 %|  85.54 %|    -    |
--+---------+---------+---------+
Rates are calculated by dividing the row's value to the column's.

尽管如此,这个堆栈似乎实际上是getting slower个.

.net相关问答推荐

.NET 7,8 System.Text.Json反序列化多态参数

在PowerShell中,XML子对象和属性是对象属性.它怎麽工作?

DotNet COM初始化问题

AppShell - 返回导航失败,匹配的路由不明确......但我只注册了一次路由

cmd 冻结中的 dotnet 命令.怎么了?

将 Span 传递到函数时出现 F# 错误

如何从标头中检索基本身份验证凭据?

Unity 2.0:如何使用 Resolve 和 ResolverOverride?

为什么我得到 411 Length required 错误?

C# 的部分类是糟糕的设计吗?

为什么要判断这个!= null?

带有输入字段的消息框

获取类型的默认构造函数的最有效方法

是否有 TLS 1.2 的 .NET 实现?

如何制作通用类型转换函数

如何仅在需要时提升权限?

如何知道 DateTime 是否在 C# 中的 DateRange 之间

立即检测客户端与服务器套接字的断开连接

将 SignalR 2.0 .NET 客户端重新连接到服务器集线器的最佳实践

对构造函数进行单元测试重要吗?