Skip to content

Conversation

keegan-caruso
Copy link
Contributor

@keegan-caruso keegan-caruso commented Dec 5, 2024

EDIT: this has been extended to also work with CoreCLR-VM so that we can resolve #113344 with it.

If a native AOT compiled application can lower its allocated memory, more scenarios that are memory sensitive can use it.

The default stack size can be excessive for simple applications and can significantly contribute to the RSS.

For linux, there is the ulimit command, and this is respected, but it can be too broad.

With this trivial code:

int s = 0;

await Task.Run(() => Interlocked.Increment(ref s));

Console.ReadLine();

On linux with the default stack size of 8mb, RSS measured at 5916.

With setting the stack size to 1mb, the RSS measured at 3428.

Roughly a 40% decrease.

@dotnet-policy-service dotnet-policy-service bot added the community-contribution Indicates that the PR has been added by a community member label Dec 5, 2024
@jkotas
Copy link
Member

jkotas commented Dec 6, 2024

We have (undocumented) IlcDefaultStackSize build property to set the default stack size in Native AOT binaries. Would it be sufficient for what you are trying to do?

@keegan-caruso
Copy link
Contributor Author

We have (undocumented) IlcDefaultStackSize build property to set the default stack size in Native AOT binaries. Would it be sufficient for what you are trying to do?

Thanks. This works on Windows, it is not working for me on Linux.

On windows I checked against kernel32 GetCurrentThreadStackLimits. On linux I checked against strace.

@jkotas
Copy link
Member

jkotas commented Dec 8, 2024

Thanks. This works on Windows, it is not working for me on Linux.

It works for musl libc (musl libc is used e.g. by Alpine Linux). glibc that is used by the most popular Linux distros like Ubuntu does not respect value set by -z,stack-size linker switch for some reason. That's unfortunate.

@jkotas
Copy link
Member

jkotas commented Feb 10, 2025

Github status is stuck in "Checking for ability to merge automatically…".

Could you please rebase against main and force push? Hopefully, it is going to reset the status.

@MichalStrehovsky
Copy link
Member

MichalStrehovsky commented Mar 13, 2025

I think we should look at this in the context of #113344:

Here's a couple questions I have:

  • Are we happy with the name of the runtimeconfig.json name of this and DOTNET_ environment variable? (They look good to me.)
  • Are we happy with the radix? (I assume we want to keep it as base-16.)

If so, I can add the CoreCLR version so that we can also resolve #113344 and we can doc it.

Cc @kouvel @AaronRobinsonMSFT for opinion

@am11
Copy link
Member

am11 commented Mar 13, 2025

The naming looks good as it's consistent with:

src/libraries/System.Private.CoreLib/src/System/Threading/PortableThreadPool.cs:            AppContextConfigHelper.GetInt16ComPlusOrDotNetConfig("System.Threading.ThreadPool.MinThreads", "ThreadPool_ForceMinWorkerThreads", 0, false);
src/libraries/System.Private.CoreLib/src/System/Threading/PortableThreadPool.cs:            AppContextConfigHelper.GetInt16ComPlusOrDotNetConfig("System.Threading.ThreadPool.MaxThreads", "ThreadPool_ForceMaxWorkerThreads", 0, false);
src/libraries/System.Private.CoreLib/src/System/Threading/ThreadPool.Unix.cs:            AppContextConfigHelper.GetBooleanConfig("System.Threading.ThreadPool.EnableWorkerTracking", "DOTNET_ThreadPool_EnableWorkerTracking");
src/libraries/System.Private.CoreLib/src/System/Threading/ThreadPool.Windows.cs:            AppContextConfigHelper.GetBooleanConfig("System.Threading.ThreadPool.UseWindowsThreadPool", "DOTNET_ThreadPool_UseWindowsThreadPool");

@AaronRobinsonMSFT
Copy link
Member

@MichalStrehovsky See #113344 also.

Are we happy with the name of the runtimeconfig.json name of this and DOTNET_ environment variable? (They look good to me.)

I didn't see the DOTNET_ environment variable. Can you point me to it?

Are we happy with the radix? (I assume we want to keep it as base-16.)

This was a source of confusion on a partner team who had been assuming it was radix 10 for about 6 years. I think having it as radix 16 is fine, but we need to document this properly at https://learn.microsoft.com/dotnet/core/runtime-config/threading.

@AaronRobinsonMSFT
Copy link
Member

DOTNET_DefaultStackSize

Seems reasonable to me.

@am11
Copy link
Member

am11 commented Mar 13, 2025

I didn't see the DOTNET_ environment variable. Can you point me to it?

It's DOTNET_Threading_DefaultStackSize. Prefix is added later. It's consistent with existing convention DOTNET_ThreadPool_UseWindowsThreadPool, DOTNET_ThreadPool_EnableWorkerTracking etc.

@kouvel
Copy link
Contributor

kouvel commented Mar 20, 2025

It's DOTNET_Threading_DefaultStackSize. Prefix is added later. It's consistent with existing convention DOTNET_ThreadPool_UseWindowsThreadPool, DOTNET_ThreadPool_EnableWorkerTracking etc.

CoreCLR already has a DOTNET_DefaultStackSize config setting. There are other thread-specific settings with DOTNET_Thread_*. Should we use the DOTNET_Thread_ prefix for consistency and add the new one to CoreCLR as well?

@MichalStrehovsky
Copy link
Member

CoreCLR already has a DOTNET_DefaultStackSize config setting. There are other thread-specific settings with DOTNET_Thread_*. Should we use the DOTNET_Thread_ prefix for consistency and add the new one to CoreCLR as well?

Made this change and standardized on DOTNET_Thread. Note there are some external hits for COMPlus_DefaultStackSize but I guess we should be fine with breaking them, otherwise there's no point in the INTERNAL and EXTERNAL prefixes for CLRConfigs.

I left DEFAULT_STACK_SIZE as is. We could probably delete it in favor of the new System.Threading.DefaultStackSize.

@MichalStrehovsky
Copy link
Member

@VSadov is this something you'd be able to review? Could you please have a look?

Copy link
Member

@AaronRobinsonMSFT AaronRobinsonMSFT left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM.

MichalStrehovsky added a commit to dotnet/docs that referenced this pull request Jul 25, 2025
@MichalStrehovsky MichalStrehovsky merged commit e1d6402 into dotnet:main Jul 25, 2025
96 of 99 checks passed
MichalStrehovsky added a commit to MichalStrehovsky/runtime that referenced this pull request Jul 25, 2025
@jkotas
Copy link
Member

jkotas commented Jul 25, 2025

We still read DOTNET_DefaultStackSize here: https://github.com/dotnet/runtime/blob/main/src/coreclr/pal/src/init/pal.cpp#L251 . Do we need to change that as well?

@jkotas
Copy link
Member

jkotas commented Jul 25, 2025

My point is that we have changed DefaultStackSize to Thread_DefaultStackSize in one place, but not in the other place.

if (g_pRhConfig->ReadConfigValue("Thread_DefaultStackSize", &uiStacksize)
|| g_pRhConfig->ReadKnobUInt64Value("System.Threading.DefaultStackSize", &uiStacksize))
{
if (uiStacksize < maxStack || uiStacksize >= minStack)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why || and not &&. I assume it is always true now?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch! #118077

@MichalStrehovsky
Copy link
Member

We still read DOTNET_DefaultStackSize here: https://github.com/dotnet/runtime/blob/main/src/coreclr/pal/src/init/pal.cpp#L251 . Do we need to change that as well?

Good catch! #118076

@github-actions github-actions bot locked and limited conversation to collaborators Aug 25, 2025
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

area-NativeAOT-coreclr community-contribution Indicates that the PR has been added by a community member

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Officially document and update the DEFAULT_STACK_SIZE app property

7 participants