Mono 下的堆栈大小

Stack size under Mono(Mono 下的堆栈大小)
本文介绍了Mono 下的堆栈大小的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我编写了一小段递归 F# 代码,以查看在 .NET/Mono 下我可以将多少级递归放入堆栈中.只要递归深度是 2 的精确幂,它就会打印递归深度,因此我会找出最大深度在 2 倍以内.

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

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

一个明显的解释是,如果 Thread 的第二个参数太大,Mono 将不会服从它.请问有人知道如何说服 Mono 分配一个大堆栈吗?

代码很简单,但在下面以防万一有人关心:

让 rec f i =if popcount i = 1 then//人口计数是 2 的精确幂次方printf "达到 %d
" i标准输出.Flush()如果 i = 1000000000 那么 0 否则 1 + f (i+1)

解决方案

选项 1:更改 Mono 堆栈大小

<块引用>

一个明显的解释是,如果 Thread 的第二个参数太大,Mono 将不会服从它.请问有人知道如何说服 Mono 分配一个大堆栈吗?

你是正确的,Mono 会限制堆栈大小,即使你传入一个很大的值.例如,在我的 Cent OS 64 位测试机器上,Mono 将分配的最大堆栈大小为 2 兆字节.Mono C# 源文件 Thread.cs 向我们展示了当您创建 Mono 线程时会发生什么:

<上一页>公共线程(ThreadStart 开始,int maxStackSize){如果(开始 == 空)抛出新的 ArgumentNullException(开始");线程启动 = 开始;Internal.stack_size = CheckStackSize (maxStackSize);}静态 int CheckStackSize (int maxStackSize){if (maxStackSize <0)throw new ArgumentOutOfRangeException ("小于零", "maxStackSize");if (maxStackSize < 131072)//确保栈至少有 128k 大返回 131072;int page_size = Environment.GetPageSize ();if ((maxStackSize % page_size) != 0)//向上舍入到页面大小的整除maxStackSize = (maxStackSize/(page_size - 1)) * page_size;<强>int default_stack_size = (IntPtr.Size/4) * 1024 * 1024;//来自 wthreads.cif (maxStackSize > default_stack_size)返回默认堆栈大小;返回最大堆栈大小;}

上面的代码对堆栈大小设置了硬性限制.

理论上,您可以更改上述一个或两个函数中的代码(粗线),以便分配更大的堆栈大小.完成此操作后,您必须构建 Mono 运行时,然后运行您的函数以查看更改是否会产生影响.

我应该强调,我对 Mono 的了解还不够,无法理解分配更大的堆栈是否会对您的特定情况有所帮助.我只会将此作为最后的手段(如果我的其他答案都不起作用).

I have written a tiny recursive bit of F# code to see how many levels of recursion I can fit onto the stack under .NET/Mono. It just prints the recursion depth whenever it is an exact power of 2, so I find out the maximum depth to within a factor 2.

I start the code in a thread with a defined amount of stack space using System.Threading.Thread (ThreadStart, int). Under .Net it seems to take approx 100 bytes per level of recursion, and I can get about 16 million levels on a 2G stack. The memory usage is broadly similar under Mono, however I can only get about 30 thousand levels. Increasing the stack size value passed to Thread past over about 600000 does not increase the recursion depth.

ulimit reports the stack size limit is 1G.

An obvious explanation is that Mono will not obey the second argument of Thread if it is too large. Does anybody please know how to convince Mono to allocate a large stack?

The code is trivial, but it's below just in case someone cares:

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

解决方案

Option 1: Change Mono Stack Size

An obvious explanation is that Mono will not obey the second argument of Thread if it is too large. Does anybody please know how to convince Mono to allocate a large stack?

You are correct that Mono will limit the stack size, even if you pass in a large value. For example, on my Cent OS 64-bit test machine, the maximum stack size that Mono will allocate is 2 megabytes. The Mono C# source file Thread.cs shows us what happens when you create a Mono thread:

public Thread (ThreadStart start, int maxStackSize)
{
    if (start == null)
        throw new ArgumentNullException ("start");

    threadstart = start;
    Internal.stack_size = CheckStackSize (maxStackSize);
}

static int CheckStackSize (int maxStackSize)
{
    if (maxStackSize < 0)
        throw new ArgumentOutOfRangeException ("less than zero", "maxStackSize");

    if (maxStackSize < 131072) // make sure stack is at least 128k big
        return 131072;

    int page_size = Environment.GetPageSize ();

    if ((maxStackSize % page_size) != 0) // round up to a divisible of page size
        maxStackSize = (maxStackSize / (page_size - 1)) * page_size;

    int default_stack_size = (IntPtr.Size / 4) * 1024 * 1024; // from wthreads.c
    if (maxStackSize > default_stack_size)
        return default_stack_size;

    return maxStackSize; 
}

The code above puts a hard limit on the stack size.

You could in theory change code in one or both of the above functions (bold lines) so that a larger stack size is allocated. Once you did this you would have to build the Mono runtime and then run your function to see if the change makes a difference.

I should stress that I do not know enough about Mono to understand if allocating a larger stack will help in your specific case. I would only do this as a last resort (if neither of my other answers work).

这篇关于Mono 下的堆栈大小的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!

本站部分内容来源互联网,如果有图片或者内容侵犯您的权益请联系我们删除!

相关文档推荐

c# Generic Setlt;Tgt; implementation to access objects by type(按类型访问对象的C#泛型集实现)
InvalidOperationException When using Context Injection in ASP.Net Core(在ASP.NET核心中使用上下文注入时发生InvalidOperationException)
quot;Overflowquot; compiler error with -9223372036854775808L(编译器错误-9223372036854775808L(Q;溢出Q))
Visual Studio 2010 ReportViewer Assembly References(Visual Studio 2010 ReportViewer程序集引用)
Weird behaviour when I open a reportviewer in WPF(在WPF中打开报表查看器时出现奇怪的行为)
how do i pass parameters to aspnet reportviewer(如何将参数传递给aspnet report查看器)