Skip to content

adding the region range and size configs #46217

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: main
Choose a base branch
from

Conversation

Maoni0
Copy link
Member

@Maoni0 Maoni0 commented May 14, 2025

2 configs for regions. lately we've been seeing a few cases where these could be beneficial.


Internal previews

📄 File 🔗 Preview link
docs/core/runtime-config/garbage-collector.md Runtime configuration options for garbage collection

@Maoni0 Maoni0 requested review from gewarren and a team as code owners May 14, 2025 21:18
@dotnetrepoman dotnetrepoman bot added this to the May 2025 milestone May 14, 2025
@Maoni0
Copy link
Member Author

Maoni0 commented May 14, 2025

@agocke - please let me know if the RegionRange config is clear enough.

@mangod9 please do a general review.

@@ -562,6 +564,41 @@ These configuration settings don't have specific MSBuild properties. However, yo
> [!TIP]
> If you're setting the option in *runtimeconfig.json*, specify a decimal value. If you're setting the option as an environment variable, specify a hexadecimal value. For example, to limit the heap usage to 30%, the values would be 30 for the JSON file and 0x1E or 1E for the environment variable.

### Region range

Starting with .NET 7.0 the GC heap switched its physical representation from segments to regions for 64-bit Windows and Linux. See [Maoni Stephens' blog article](https://itnext.io/how-segments-and-regions-differ-in-decommitting-memory-in-the-net-7-gc-68c58465ab5a) for more details. With this change the GC reserves a range of virtual memory during initialization. Note that this is only reserving memory, not committing (the GC heap size is committed memory). It's merely a range to define the maximum range the GC heap can commit. For most applications they don't need to commit nearly this much.
Copy link
Member

Choose a reason for hiding this comment

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

It might be good to outline what this value could be reasonably set to. For instance, if the user thinks that their working set is max 1GB, is it reasonable to set this to 2 GB? How will changing the range affect the performance of the GC? If they don't know the working set of their app, is 2x physical memory a better pick?

@@ -562,6 +564,41 @@ These configuration settings don't have specific MSBuild properties. However, yo
> [!TIP]
> If you're setting the option in *runtimeconfig.json*, specify a decimal value. If you're setting the option as an environment variable, specify a hexadecimal value. For example, to limit the heap usage to 30%, the values would be 30 for the JSON file and 0x1E or 1E for the environment variable.

### Region range

Starting with .NET 7.0 the GC heap switched its physical representation from segments to regions for 64-bit Windows and Linux. See [Maoni Stephens' blog article](https://itnext.io/how-segments-and-regions-differ-in-decommitting-memory-in-the-net-7-gc-68c58465ab5a) for more details. With this change the GC reserves a range of virtual memory during initialization. Note that this is only reserving memory, not committing (the GC heap size is committed memory). It's merely a range to define the maximum range the GC heap can commit. For most applications they don't need to commit nearly this much.
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
Starting with .NET 7.0 the GC heap switched its physical representation from segments to regions for 64-bit Windows and Linux. See [Maoni Stephens' blog article](https://itnext.io/how-segments-and-regions-differ-in-decommitting-memory-in-the-net-7-gc-68c58465ab5a) for more details. With this change the GC reserves a range of virtual memory during initialization. Note that this is only reserving memory, not committing (the GC heap size is committed memory). It's merely a range to define the maximum range the GC heap can commit. For most applications they don't need to commit nearly this much.
Starting in .NET 7, the GC heap switched its physical representation from segments to regions for 64-bit Windows and Linux. (For more information, see [Maoni Stephens' blog article](https://itnext.io/how-segments-and-regions-differ-in-decommitting-memory-in-the-net-7-gc-68c58465ab5a).) With this change, the GC reserves a range of virtual memory during initialization. Note that this is only reserving memory, not committing (the GC heap size is committed memory). It's merely a range to define the maximum range the GC heap can commit. Most applications don't need to commit nearly this much.


Starting with .NET 7.0 the GC heap switched its physical representation from segments to regions for 64-bit Windows and Linux. See [Maoni Stephens' blog article](https://itnext.io/how-segments-and-regions-differ-in-decommitting-memory-in-the-net-7-gc-68c58465ab5a) for more details. With this change the GC reserves a range of virtual memory during initialization. Note that this is only reserving memory, not committing (the GC heap size is committed memory). It's merely a range to define the maximum range the GC heap can commit. For most applications they don't need to commit nearly this much.

If you don't have any other configurations and aren't running in a memory constraint environment (which would cause some GC configs to be set), by default we reserve 256GB. If you have more than 256GB physical memory available, it will be twice that amount.
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
If you don't have any other configurations and aren't running in a memory constraint environment (which would cause some GC configs to be set), by default we reserve 256GB. If you have more than 256GB physical memory available, it will be twice that amount.
If you don't have any other configurations and aren't running in a memory-constrained environment (which would cause some GC configs to be set), by default 256 GB is reserved. If you have more than 256 GB physical memory available, it will be twice that amount.


If you don't have any other configurations and aren't running in a memory constraint environment (which would cause some GC configs to be set), by default we reserve 256GB. If you have more than 256GB physical memory available, it will be twice that amount.

If the per heap hard limits are set, the reserve range will be the same as the total hard limit. If a single hard limit config is set, this range will be 5x that amount.
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
If the per heap hard limits are set, the reserve range will be the same as the total hard limit. If a single hard limit config is set, this range will be 5x that amount.
If the per heap hard limits are set, the reserve range is the same as the total hard limit. If a single hard limit config is set, this range is five times that amount.


If the per heap hard limits are set, the reserve range will be the same as the total hard limit. If a single hard limit config is set, this range will be 5x that amount.

This range is limited by the amount of total virtual memory. Normally on 64-bit this is never a problem but there could be a virtual memory limit set on a process. This range will be limited by half that amount. For example, if you set the HeapHardLimit config to 1GB and have a 4GB virtual memory limit set on the process, this range will be min (5x1GB, 4GB/2) which is 2GB.
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
This range is limited by the amount of total virtual memory. Normally on 64-bit this is never a problem but there could be a virtual memory limit set on a process. This range will be limited by half that amount. For example, if you set the HeapHardLimit config to 1GB and have a 4GB virtual memory limit set on the process, this range will be min (5x1GB, 4GB/2) which is 2GB.
This range is limited by the amount of total virtual memory. Normally on 64-bit this is never a problem, but there could be a virtual memory limit set on a process. This range is limited by half that amount. For example, if you set the `HeapHardLimit` config to 1 GB and have a 4 GB virtual memory limit set on the process, this range is `min (5x1GB, 4GB/2)`, which is 2 GB.


This range is limited by the amount of total virtual memory. Normally on 64-bit this is never a problem but there could be a virtual memory limit set on a process. This range will be limited by half that amount. For example, if you set the HeapHardLimit config to 1GB and have a 4GB virtual memory limit set on the process, this range will be min (5x1GB, 4GB/2) which is 2GB.

You can use the `GC.GetConfigurationVariables` API to see the value of this range under the name `GCRegionRange`. If you do get `E_OUTOFMEMORY` during the runtime intialization and want to see if it's due to reserving this range, you can look at the `VirtualAlloc`call with `MEM_RESERVE` on Windows and the `mmap` call with `PROT_NONE` on Linux during GC initialization and see if the OOM is from that call. If this reserve call is failing you can change it via this config.
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
You can use the `GC.GetConfigurationVariables` API to see the value of this range under the name `GCRegionRange`. If you do get `E_OUTOFMEMORY` during the runtime intialization and want to see if it's due to reserving this range, you can look at the `VirtualAlloc`call with `MEM_RESERVE` on Windows and the `mmap` call with `PROT_NONE` on Linux during GC initialization and see if the OOM is from that call. If this reserve call is failing you can change it via this config.
You can use the `GC.GetConfigurationVariables` API to see the value of this range under the name `GCRegionRange`. If you do get `E_OUTOFMEMORY` during the runtime intialization and want to see if it's due to reserving this range, you can look at the `VirtualAlloc`call with `MEM_RESERVE` on Windows and the `mmap` call with `PROT_NONE` on Linux during GC initialization and see if the OOM is from that call. If this reserve call is failing, you can change it via the following configuration settings.


### Region size

Starting with .NET 7.0 the GC heap switched its physical representation from segments to regions for 64-bit Windows and Linux. See [Maoni Stephens' blog article](https://itnext.io/how-segments-and-regions-differ-in-decommitting-memory-in-the-net-7-gc-68c58465ab5a) for more details. By default each region is 4MB for SOH. For UOH (LOH and POH), it's 8 times the SOH region size. You can use this config to change the SOH region size and the UOH regions will be adjusted accordingly.
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
Starting with .NET 7.0 the GC heap switched its physical representation from segments to regions for 64-bit Windows and Linux. See [Maoni Stephens' blog article](https://itnext.io/how-segments-and-regions-differ-in-decommitting-memory-in-the-net-7-gc-68c58465ab5a) for more details. By default each region is 4MB for SOH. For UOH (LOH and POH), it's 8 times the SOH region size. You can use this config to change the SOH region size and the UOH regions will be adjusted accordingly.
Starting with .NET 7, the GC heap switched its physical representation from segments to regions for 64-bit Windows and Linux. (For more information, see [Maoni Stephens' blog article](https://itnext.io/how-segments-and-regions-differ-in-decommitting-memory-in-the-net-7-gc-68c58465ab5a).) By default, each region is 4 MB for SOH. For UOH (LOH and POH), it's eight times the SOH region size. You can use this config to change the SOH region size, and the UOH regions will be adjusted accordingly.


Starting with .NET 7.0 the GC heap switched its physical representation from segments to regions for 64-bit Windows and Linux. See [Maoni Stephens' blog article](https://itnext.io/how-segments-and-regions-differ-in-decommitting-memory-in-the-net-7-gc-68c58465ab5a) for more details. By default each region is 4MB for SOH. For UOH (LOH and POH), it's 8 times the SOH region size. You can use this config to change the SOH region size and the UOH regions will be adjusted accordingly.

Regions are only allocated when needed so in general you don't need to care about the region size. However there are 2 cases where you might want to adjust this size and use
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
Regions are only allocated when needed so in general you don't need to care about the region size. However there are 2 cases where you might want to adjust this size and use
Regions are only allocated when needed, so in general you don't need to worry about the region size. However, there are two cases where you might want to adjust this size:


Regions are only allocated when needed so in general you don't need to care about the region size. However there are 2 cases where you might want to adjust this size and use

- For processes that have very small GC heaps, changing the region size to be smaller would be beneficial for native memory usage from GC's own bookkeeping. The recommendation is 1MB.
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
- For processes that have very small GC heaps, changing the region size to be smaller would be beneficial for native memory usage from GC's own bookkeeping. The recommendation is 1MB.
- For processes that have very small GC heaps, changing the region size to be smaller is beneficial for native memory usage from GC's own bookkeeping. The recommendation is 1 MB.

Regions are only allocated when needed so in general you don't need to care about the region size. However there are 2 cases where you might want to adjust this size and use

- For processes that have very small GC heaps, changing the region size to be smaller would be beneficial for native memory usage from GC's own bookkeeping. The recommendation is 1MB.
- If you are on Linux and need to reduce the number of memory mappings, you can change this to be larger, eg, 32MB.
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
- If you are on Linux and need to reduce the number of memory mappings, you can change this to be larger, eg, 32MB.
- On Linux, if you need to reduce the number of memory mappings, you can change the region size to be larger, for example, 32 MB.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants