Is there a way to check threads stack size in C#?
相关问题
- Sorting 3 numbers without branching [closed]
- Graphics.DrawImage() - Throws out of memory except
- Why am I getting UnauthorizedAccessException on th
- 求获取指定qq 资料的方法
- How to know full paths to DLL's from .csproj f
I'm adding this answer for my future reference. :-)
Oren's answer answers the SO's question (as refined by the comment), but it does not indicate how much memory was actually allocated for the stack to begin with. To get that answer, you can use the Michael Ganß's answer here, which I've updated below using some more recent C# syntax.
What is interesting (and the reason I'm posting this) is the output when run using different configurations. For reference, I'm running this on a Windows 10 Enterprise (Build 1709) 64-bit OS using .NET Framework 4.7.2 (if it matters).
Release|Any CPU (Prefer 32-bit option checked):
Release|Any CPU (Prefer 32-bit option unchecked):
Release|x86:
Release|x64:
There's nothing particularly shocking about these results given that they are consistent with the documentation. What was a little bit surprising, though, was the default stack size is 1 MB when running in the Release|Any CPU configuration with the Prefer 32-bit option unchecked, meaning it runs as a 64-bit process on a 64-bit OS. I would have assumed the default stack size in this case would've been 4 MB like the Release|x64 configuration.
In any case, I hope this might be of use to someone who lands here wanting to know about the stack size of a .NET thread, like I did.
This is a case of if you have to ask, you can't afford it (Raymond Chen said it first.) If the code depends on there being enough stack space to the extent that it has to check first, it might be worthwhile to refactor it to use an explicit
Stack<T>
object instead. There's merit in John's comment about using a profiler instead.That said, it turns out that there is a way to estimate the remaining stack space. It's not precise, but it's useful enough for the purpose of evaluating how close to the bottom you are. The following is heavily based on an excellent article by Joe Duffy.
We know (or will make the assumptions) that:
With these assumptions, we could pinvoke VirtualQuery to obtain the start address of the allocated stack, and subtract it from the address of some stack-allocated variable (obtained with unsafe code.) Further subtracting our estimate of the space the system needs at the bottom of the stack would give us an estimate of the available space.
The code below demonstrates this by invoking a recursive function and writing out the remaining estimated stack space, in bytes, as it goes:
And here are the first 10 lines of output (intel x64, .NET 4.0, debug). Given the 1MB default stack size, the counts appear plausible.
For brevity, the code above assumes a page size of 4K. While that holds true for x86 and x64, it might not be correct for other supported CLR architectures. You could pinvoke into GetSystemInfo to obtain the machine's page size (the dwPageSize of the SYSTEM_INFO struct).
Note that this technique isn't particularly portable, nor is it future proof. The use of pinvoke limits the utility of this approach to Windows hosts. The assumptions about the continuity and direction of growth of the CLR stack may hold true for the present Microsoft implementations. However, my (possibly limited) reading of the CLI standard (common language infrastructure, PDF, a long read) does not appear to demand as much of thread stacks. As far as the CLI is concerned, each method invocation requires a stack frame; it couldn't care less, however, if stacks grow upward, if local variable stacks are separate from return value stacks, or if stack frames are allocated on the heap.