相关疑难解决方法(0)

创建堆栈大小为默认值50倍的线程有什么危险?

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

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

我知道这通常被认为是"不安全的"并且不推荐,但在对我的当前代码进行基准测试后,我发现处理速度提高了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;
    }
}
Run Code Online (Sandbox Code Playgroud)

.net c# memory stack-memory

228
推荐指数
7
解决办法
5286
查看次数

为什么C#中的堆栈大小正好是1 MB?

今天的PC有大量的物理RAM,但是C#的堆栈大小对于32位进程只有1 MB而对于64位进程只有4 MB(C#中的堆栈容量).

为什么CLR中的堆栈大小仍然如此有限?

为什么它恰好是1 MB(4 MB)(而不是2 MB或512 KB)?为什么决定使用这些金额?

对该决定背后的考虑因素和原因感兴趣.

c# clr stack stack-size

87
推荐指数
2
解决办法
3万
查看次数

F#vs OCaml:堆栈溢出

我最近在Python程序员面前发现了一个关于F#的演示文稿,看了之后,我决定自己实现"蚂蚁拼图"的解决方案.

有一只蚂蚁可以在平面网格上走动.蚂蚁可以一次向左,向右,向上或向下移动一个空间.也就是说,从单元格(x,y),蚂蚁可以进入单元格(x + 1,y),(x-1,y),(x,y + 1)和(x,y-1).蚂蚁无法访问x和y坐标的数字之和大于25的点.例如,点(59,79)是不可访问的,因为5 + 9 + 7 + 9 = 30,大于25.问题是:如果从(1000,1000)开始,蚂蚁可以访问多少个点,包括(1000,1000)本身?

首先在30行OCaml中实现了我的解决方案,并尝试了它:

$ ocamlopt -unsafe -rectypes -inline 1000 -o puzzle ant.ml
$ time ./puzzle
Points: 148848

real    0m0.143s
user    0m0.127s
sys     0m0.013s
Run Code Online (Sandbox Code Playgroud)

整洁,我的结果与leonardo在D和C++中的实现相同.与leonardo的C++实现相比,OCaml版本的运行速度比C++慢大约2倍.这是好的,因为leonardo使用队列来删除递归.

然后我将代码翻译成F# ......这就是我得到的:

Thanassis@HOME /g/Tmp/ant.fsharp
$ /g/Program\ Files/FSharp-2.0.0.0/bin/fsc.exe ant.fs
Microsoft (R) F# 2.0 Compiler build 2.0.0.0
Copyright (c) Microsoft Corporation. All Rights Reserved.

Thanassis@HOME /g/Tmp/ant.fsharp
$ ./ant.exe

Process is terminated due to StackOverflowException.
Quit …
Run Code Online (Sandbox Code Playgroud)

stack-overflow f# ocaml tail-recursion

61
推荐指数
2
解决办法
1万
查看次数

单声道下的堆栈大小

我编写了一个很小的递归F#代码来查看我可以在.NET/Mono下的堆栈中放入多少级别的递归.它只是在精确的2次幂时打印递归深度,所以我发现最大深度在2的范围内.

我在一个具有定义的堆栈空间量的线程中启动代码System.Threading.Thread (ThreadStart, int).在.Net下,每个递归级别似乎需要大约100个字节,而我可以在2G堆栈上获得大约1600万个级别.Mono下的内存使用情况大致相似,但是我只能获得大约3万个级别.增加传递给Thread过去的堆栈大小值600000不会增加递归深度.

ulimit 报告堆栈大小限制为1G.

一个明显的解释是Mono不会服从第二个论点,Thread如果它太大了.有没有人知道如何说服Mono分配一个大堆栈?

代码是微不足道的,但它只是在某些人关心的情况下:

let rec f i =
    if popcount i = 1 then // population count is one on exact powers of 2
        printf "Got up to %d\n" i
        stdout.Flush ()
    if i = 1000000000 then 0 else 1 + f (i+1)
Run Code Online (Sandbox Code Playgroud)

.net mono recursion f#

10
推荐指数
1
解决办法
2095
查看次数

方法中的最大变量数

我在这里闲着,所以我有这种好奇心,有人可以告诉我C#中每种方法的最大变量数是多少?

c#

9
推荐指数
2
解决办法
1349
查看次数

即使是局部变量,C#decimal的值是否也存储在堆上?

当C#decimal是局部变量时,它是否存储在堆上?

我(相信)知道的

  • decimal结构有16个字节.
  • 类型的局部变量的ValueType值存储在堆栈中,并decimal继承自ValueType.
  • 在32位系统上,参考存储空间只有4个字节; 参考存储空间我的意思是下面的方框标记为例如bazbar 在此输入图像描述

    图像来源.

  • 因为ValueTypes,这是存储价值的地方; 对于引用类型,这null是存储堆内存位置的任一个或引用.

decimal在32位系统上只有4个字节可用的情况下,a 的值(16字节大)如何存储在堆栈中?

我的想法出了什么问题?

我读过的

c# stack heap-memory

7
推荐指数
1
解决办法
605
查看次数

C#中的调用堆栈限制

我想知道在我们得到堆栈溢出异常之前我们可以在c#中执行多少调用

所以我决定写下面的代码

    static void Method2(int Calls)
    {
        if(!Calls.Equals(0))
            Method1(--Calls);//if more calls remain call method1 and reduce counter
    }
    static void Method1(int Calls)
    {
        if (!Calls.Equals(0))//if more calls remain call method2 and reduce counter
            Method2(--Calls);

    }
    static void Main(string[] args)
    {
        var Calls= 42994;//number of calls(stack overflow appears for large number)
        Method1(Calls);
    }
Run Code Online (Sandbox Code Playgroud)

我的问题是编译器如何决定抛出堆栈溢出异常是关于内存限制的?一旦我把42995我得到stackoverflow但这个数字不是恒定所以这是如何工作的?

c# stack-overflow callstack limits

4
推荐指数
1
解决办法
6449
查看次数

递归堆栈大小?

class Program  
{
    static void Main(string[] args)
    {
        Test(0);
    }

    static void Test(int i)
    {
        if (i > 30000)
        {
            return;
        }
        Test(i + 1);
    }
}
Run Code Online (Sandbox Code Playgroud)

为什么在调用上面的示例时获取递归函数并抛出StackOverflowException.

(因为超过默认的递归堆栈大小?)

但我想知道如何解决这个问题.

谢谢.

c# recursion overflowexception

2
推荐指数
2
解决办法
4557
查看次数

流到 UTF8 字符串,不带字节 []

我有一个流,其下N个字节是 UTF8 编码的字符串。我想以最少的开销创建该字符串。

这有效:

var bytes = new byte[n];
stream.Read(bytes, 0, n); // my actual code checks return value
var str = Encoding.UTF8.GetString(bytes);
Run Code Online (Sandbox Code Playgroud)

在我的基准测试中,我看到花费了大量时间以byte[]临时形式收集垃圾。如果我可以摆脱这些,我可以有效地将我的堆分配减半。

UTF8Encoding类没有与流工作方法。

如果有帮助,我可以使用不安全的代码。我不能重用一个byte[]缓冲区,如果没有ThreadLocal<byte[]>它似乎引入了比它减轻的更多的开销。我确实需要支持 UTF8(ASCII 不会削减它)。

这里有我缺少的 API 或技术吗?

.net c# performance stream character-encoding

1
推荐指数
1
解决办法
1723
查看次数

堆栈溢出异常中c ++和c#之间的区别

当我在C#中编写一些代码时,我有一个递归方法,在几千次调用后导致堆栈溢出异常.
所以过了一会儿,我在C++中编写了相同的代码,它没有例外地工作得很好(即使递归调用的实际数量比C#停止的地方大10倍).
C#和C++在处理这个问题上有什么区别?有没有什么方法可以允许在C#中进行更多的递归调用而不抛出异常?

c# c++ stack-overflow recursion

1
推荐指数
1
解决办法
136
查看次数