Fix an issue with the last level cache values on Linux running on certain AMD Processors - #108492

Merged
mrsharm merged 12 commits into
dotnet:mainfrom
mrsharm:lastlevelcache_refactor
Oct 11, 2024
Merged

Fix an issue with the last level cache values on Linux running on certain AMD Processors#108492
mrsharm merged 12 commits into
dotnet:mainfrom
mrsharm:lastlevelcache_refactor

Conversation

@mrsharm

@mrsharmmrsharm commented Oct 2, 2024

Copy link
Copy Markdown
Member

Fixes: #76290

Problem Details

We recently discovered an issue that affects Unix based VMs where we are taking the host’s (as opposed to the VM’s) for certain AMD processor's last level cache size to be used in the GetLogicalProcessorCacheSizeFromOS call to discern the gen0 budget for both WKS and SVR. This is because sysconf, the method we first try in GetLogicalProcessorCacheSizeFromOS, gets us the last level cache of the host machine as opposed to the fallback code path that reads the value of /sys/devices/system/cpu/cpu0/cache/index{LastLevelCache}/size. Consequently, the gen0 budgets are significantly different between Unix VMs and Windows using certain AMD processors on the same machine and the further implication of this is that we are probably setting much larger value than expected for the Gen0 budget for the GC running on Unix based VMs.

The details from my v16 CPU based DevBox with an AMD EPYC 7763 64 Core Processor running Ubuntu 22.04.3 via WSL are as follows:

  • sysconf returns the last cache size (L3) for the host machine (AMD EPYC™ 7763 – specs are here) as 256 MB.
    • Can be repro’d on the command line using:
      getconf -a | grep “LEVEL3_CACHE_SIZE” => LEVEL3_CACHE_SIZE 268435456
  • Reading /sys/devices/system/cpu/cpu0/cache/index3/size returns 32 MiB, the same as the result from GetLogicalProcessorCacheSizeFromOS from Windows that calls GetLogicalProcessorInformation function (sysinfoapi.h) - Win32 apps | Microsoft Learn.
    • Can be repro’d on the command line using lscpu => L3: 32 MiB (1 instance)

How To Check for the Issue

  1. Get sysconf output: getconf -a | grep "LEVEL"
  2. The full output of lscpu
  3. Check if the L3 (or if available, L4) cache size is the same from sysconf and that from lscpu.
  4. If the values are different, the issue exists.

Solution

  • By default, with no configuration changes, first try to read in the cache information from sysfs and if that fails, fall back to the heuristic we use to compute the value for the ARM* cases.
  • A new configuration DOTNET_GCCacheSizeFromSysConf can be set to 1 to revert to the current behavior i.e., using sysconf to obtain the last level cache.

Performance Testing

Ran with the following GCPerfSim configurations for SVR: -tc 28 -tagb 100 -tlgb 0 -lohar 0-pohar 0 -sohsr 100-4000 -lohsr 102400-204800 -pohsr 100-204800 -sohsi 0 -lohsi 0 -pohsi 0 -sohpi 0 -lohpi 0 -sohfi 0 -lohfi 0 -pohfi 0 -allocType reference -testKind time

image

MetricNot With SysConfWith SysConf
Peak Heap Size (MB)339.4582656.194
% Pause Time in GC39.07.7

Comment threadsrc/coreclr/gc/unix/gcenv.unix.cpp Outdated
@mrsharm
mrsharm marked this pull request as ready for review October 4, 2024 19:19
@mrsharmmrsharm changed the title [Work in Progress] Fix an issue with the last level cache values on Linux running on certain AMD ProcessorsFix an issue with the last level cache values on Linux running on certain AMD ProcessorsOct 4, 2024
Comment threadsrc/coreclr/gc/unix/gcenv.unix.cpp
Comment threadsrc/coreclr/gc/unix/gcenv.unix.cpp Outdated
Comment threadsrc/coreclr/gc/unix/gcenv.unix.cpp Outdated
@Maoni0

Copy link
Copy Markdown
Member

the rest looks okay to me.. would be great if @janvorli could take a look.

@janvorli

Copy link
Copy Markdown
Member

There is one thing I keep thinking about. Would it be a problem in case the /sys/devices/system/cpu/cpu0/cache is not present to still read the size from sysconf? In other words, to let the new config knob control just the order in which we try to use the /sys/devices/system/cpu/cpu0/cache and sysconf? I wonder if in the case the /sys/devices/system/cpu/cpu0/cache is missing, the heuristic fallback would give us a reasonable value.

@Maoni0

Copy link
Copy Markdown
Member

the way I look at this is from the user's POV the values from sysconf is simply incorrect. so it'd be better to just take the heuristic values. another option is to treat sysconf to always give us the full cache sizes and check to see how many cores this process is actually allowed to use and get a ratio (so if sysconf reports 128mb and 64 cores, our process can only use 8 cores, we take 1/8 of 128mb).

@janvorli

janvorli commented Oct 9, 2024

Copy link
Copy Markdown
Member

I would rather avoid introducing this new kind of heuristic, because it depends on the internal topology of the processor. One of the cases we were seeing this issue occurred on some AMD processors, because they have 4 separate 3rd level caches where each one is shared by 1/4 of the cores. In this case, the customer was using the full CPU and still the sysconf was returning a sum of the 3rd level cache sizes, it means 4 times higher value.
So let's keep this change as is.

@mrsharm

Copy link
Copy Markdown
MemberAuthor

How To Check for the Issue

  1. Get sysconf output for the last level cache size: getconf -a | grep "LEVEL"
  2. The full output of lscpu
  3. Check if the last level cache size is the same from sysconf and that from lscpu.
  4. If the values are different, the issue exists.

@mrsharm

Copy link
Copy Markdown
MemberAuthor

/backport to release/9.0-staging

@github-actions

Copy link
Copy Markdown
Contributor

Started backporting to release/9.0-staging: https://github.com/dotnet/runtime/actions/runs/11803383363

@github-actions

Copy link
Copy Markdown
Contributor

@mrsharm backporting to release/9.0-staging failed, the patch most likely resulted in conflicts:

$ git am --3way --empty=keep --ignore-whitespace --keep-non-patch changes.patch
Applying: Started work on the Last Level Cache optimization
.git/rebase-apply/patch:112: trailing whitespace.
#endif 
.git/rebase-apply/patch:152: trailing whitespace.
// It seems ok to set the same default sizes when the cache info isn’t available on the /sys/ path like we did with arm. .git/rebase-apply/patch:166: trailing whitespace.
warning: 3 lines add whitespace errors.
Using index info to reconstruct a base tree...
M	src/coreclr/gc/gcconfig.h
Falling back to patching base and 3-way merge...
Auto-merging src/coreclr/gc/gcconfig.h
CONFLICT (content): Merge conflict in src/coreclr/gc/gcconfig.h
error: Failed to merge in the changes.
hint: Use 'git am --show-current-patch=diff' to see the failed patch
hint: When you have resolved this problem, run "git am --continue".
hint: If you prefer to skip this patch, run "git am --skip" instead.
hint: To restore the original branch and stop patching, run "git am --abort".
hint: Disable this message with "git config advice.mergeConflict false"
Patch failed at 0001 Started work on the Last Level Cache optimization
Error: The process '/usr/bin/git' failed with exit code 128

Please backport manually!

@github-actions

Copy link
Copy Markdown
Contributor

@mrsharm an error occurred while backporting to release/9.0-staging, please check the run log for details!

Error: git am failed, most likely due to a merge conflict.

mikelle-rogers pushed a commit to mikelle-rogers/runtime that referenced this pull request Dec 10, 2024
@github-actionsgithub-actionsBot locked and limited conversation to collaborators Dec 13, 2024
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

GC picks wrong L3 cache size on Linux

3 participants

@mrsharm@Maoni0@janvorli
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content

Fix an issue with the last level cache values on Linux running on certain AMD Processors - #108492

Merged
mrsharm merged 12 commits into
dotnet:mainfrom
mrsharm:lastlevelcache_refactor
Oct 11, 2024
Merged

Fix an issue with the last level cache values on Linux running on certain AMD Processors#108492
mrsharm merged 12 commits into
dotnet:mainfrom
mrsharm:lastlevelcache_refactor

Conversation

@mrsharm

@mrsharmmrsharm commented Oct 2, 2024

Copy link
Copy Markdown
Member

Fixes: #76290

Problem Details

We recently discovered an issue that affects Unix based VMs where we are taking the host’s (as opposed to the VM’s) for certain AMD processor's last level cache size to be used in the GetLogicalProcessorCacheSizeFromOS call to discern the gen0 budget for both WKS and SVR. This is because sysconf, the method we first try in GetLogicalProcessorCacheSizeFromOS, gets us the last level cache of the host machine as opposed to the fallback code path that reads the value of /sys/devices/system/cpu/cpu0/cache/index{LastLevelCache}/size. Consequently, the gen0 budgets are significantly different between Unix VMs and Windows using certain AMD processors on the same machine and the further implication of this is that we are probably setting much larger value than expected for the Gen0 budget for the GC running on Unix based VMs.

The details from my v16 CPU based DevBox with an AMD EPYC 7763 64 Core Processor running Ubuntu 22.04.3 via WSL are as follows:

  • sysconf returns the last cache size (L3) for the host machine (AMD EPYC™ 7763 – specs are here) as 256 MB.
    • Can be repro’d on the command line using:
      getconf -a | grep “LEVEL3_CACHE_SIZE” => LEVEL3_CACHE_SIZE 268435456
  • Reading /sys/devices/system/cpu/cpu0/cache/index3/size returns 32 MiB, the same as the result from GetLogicalProcessorCacheSizeFromOS from Windows that calls GetLogicalProcessorInformation function (sysinfoapi.h) - Win32 apps | Microsoft Learn.
    • Can be repro’d on the command line using lscpu => L3: 32 MiB (1 instance)

How To Check for the Issue

  1. Get sysconf output: getconf -a | grep "LEVEL"
  2. The full output of lscpu
  3. Check if the L3 (or if available, L4) cache size is the same from sysconf and that from lscpu.
  4. If the values are different, the issue exists.

Solution

  • By default, with no configuration changes, first try to read in the cache information from sysfs and if that fails, fall back to the heuristic we use to compute the value for the ARM* cases.
  • A new configuration DOTNET_GCCacheSizeFromSysConf can be set to 1 to revert to the current behavior i.e., using sysconf to obtain the last level cache.

Performance Testing

Ran with the following GCPerfSim configurations for SVR: -tc 28 -tagb 100 -tlgb 0 -lohar 0-pohar 0 -sohsr 100-4000 -lohsr 102400-204800 -pohsr 100-204800 -sohsi 0 -lohsi 0 -pohsi 0 -sohpi 0 -lohpi 0 -sohfi 0 -lohfi 0 -pohfi 0 -allocType reference -testKind time

image

MetricNot With SysConfWith SysConf
Peak Heap Size (MB)339.4582656.194
% Pause Time in GC39.07.7

Comment threadsrc/coreclr/gc/unix/gcenv.unix.cpp Outdated
@mrsharm
mrsharm marked this pull request as ready for review October 4, 2024 19:19
@mrsharmmrsharm changed the title [Work in Progress] Fix an issue with the last level cache values on Linux running on certain AMD ProcessorsFix an issue with the last level cache values on Linux running on certain AMD ProcessorsOct 4, 2024
Comment threadsrc/coreclr/gc/unix/gcenv.unix.cpp
Comment threadsrc/coreclr/gc/unix/gcenv.unix.cpp Outdated
Comment threadsrc/coreclr/gc/unix/gcenv.unix.cpp Outdated
@Maoni0

Copy link
Copy Markdown
Member

the rest looks okay to me.. would be great if @janvorli could take a look.

@janvorli

Copy link
Copy Markdown
Member

There is one thing I keep thinking about. Would it be a problem in case the /sys/devices/system/cpu/cpu0/cache is not present to still read the size from sysconf? In other words, to let the new config knob control just the order in which we try to use the /sys/devices/system/cpu/cpu0/cache and sysconf? I wonder if in the case the /sys/devices/system/cpu/cpu0/cache is missing, the heuristic fallback would give us a reasonable value.

@Maoni0

Copy link
Copy Markdown
Member

the way I look at this is from the user's POV the values from sysconf is simply incorrect. so it'd be better to just take the heuristic values. another option is to treat sysconf to always give us the full cache sizes and check to see how many cores this process is actually allowed to use and get a ratio (so if sysconf reports 128mb and 64 cores, our process can only use 8 cores, we take 1/8 of 128mb).

@janvorli

janvorli commented Oct 9, 2024

Copy link
Copy Markdown
Member

I would rather avoid introducing this new kind of heuristic, because it depends on the internal topology of the processor. One of the cases we were seeing this issue occurred on some AMD processors, because they have 4 separate 3rd level caches where each one is shared by 1/4 of the cores. In this case, the customer was using the full CPU and still the sysconf was returning a sum of the 3rd level cache sizes, it means 4 times higher value.
So let's keep this change as is.

@mrsharm

Copy link
Copy Markdown
MemberAuthor

How To Check for the Issue

  1. Get sysconf output for the last level cache size: getconf -a | grep "LEVEL"
  2. The full output of lscpu
  3. Check if the last level cache size is the same from sysconf and that from lscpu.
  4. If the values are different, the issue exists.

@mrsharm

Copy link
Copy Markdown
MemberAuthor

/backport to release/9.0-staging

@github-actions

Copy link
Copy Markdown
Contributor

Started backporting to release/9.0-staging: https://github.com/dotnet/runtime/actions/runs/11803383363

@github-actions

Copy link
Copy Markdown
Contributor

@mrsharm backporting to release/9.0-staging failed, the patch most likely resulted in conflicts:

$ git am --3way --empty=keep --ignore-whitespace --keep-non-patch changes.patch
Applying: Started work on the Last Level Cache optimization
.git/rebase-apply/patch:112: trailing whitespace.
#endif 
.git/rebase-apply/patch:152: trailing whitespace.
// It seems ok to set the same default sizes when the cache info isn’t available on the /sys/ path like we did with arm. .git/rebase-apply/patch:166: trailing whitespace.
warning: 3 lines add whitespace errors.
Using index info to reconstruct a base tree...
M	src/coreclr/gc/gcconfig.h
Falling back to patching base and 3-way merge...
Auto-merging src/coreclr/gc/gcconfig.h
CONFLICT (content): Merge conflict in src/coreclr/gc/gcconfig.h
error: Failed to merge in the changes.
hint: Use 'git am --show-current-patch=diff' to see the failed patch
hint: When you have resolved this problem, run "git am --continue".
hint: If you prefer to skip this patch, run "git am --skip" instead.
hint: To restore the original branch and stop patching, run "git am --abort".
hint: Disable this message with "git config advice.mergeConflict false"
Patch failed at 0001 Started work on the Last Level Cache optimization
Error: The process '/usr/bin/git' failed with exit code 128

Please backport manually!

@github-actions

Copy link
Copy Markdown
Contributor

@mrsharm an error occurred while backporting to release/9.0-staging, please check the run log for details!

Error: git am failed, most likely due to a merge conflict.

mikelle-rogers pushed a commit to mikelle-rogers/runtime that referenced this pull request Dec 10, 2024
@github-actionsgithub-actionsBot locked and limited conversation to collaborators Dec 13, 2024
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

GC picks wrong L3 cache size on Linux

3 participants

@mrsharm@Maoni0@janvorli
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Fix an issue with the last level cache values on Linux running on certain AMD Processors - #108492

Merged
mrsharm merged 12 commits into
dotnet:mainfrom
mrsharm:lastlevelcache_refactor
Oct 11, 2024
Merged

Fix an issue with the last level cache values on Linux running on certain AMD Processors#108492
mrsharm merged 12 commits into
dotnet:mainfrom
mrsharm:lastlevelcache_refactor

Conversation

@mrsharm

@mrsharmmrsharm commented Oct 2, 2024

Copy link
Copy Markdown
Member

Fixes: #76290

Problem Details

We recently discovered an issue that affects Unix based VMs where we are taking the host’s (as opposed to the VM’s) for certain AMD processor's last level cache size to be used in the GetLogicalProcessorCacheSizeFromOS call to discern the gen0 budget for both WKS and SVR. This is because sysconf, the method we first try in GetLogicalProcessorCacheSizeFromOS, gets us the last level cache of the host machine as opposed to the fallback code path that reads the value of /sys/devices/system/cpu/cpu0/cache/index{LastLevelCache}/size. Consequently, the gen0 budgets are significantly different between Unix VMs and Windows using certain AMD processors on the same machine and the further implication of this is that we are probably setting much larger value than expected for the Gen0 budget for the GC running on Unix based VMs.

The details from my v16 CPU based DevBox with an AMD EPYC 7763 64 Core Processor running Ubuntu 22.04.3 via WSL are as follows:

  • sysconf returns the last cache size (L3) for the host machine (AMD EPYC™ 7763 – specs are here) as 256 MB.
    • Can be repro’d on the command line using:
      getconf -a | grep “LEVEL3_CACHE_SIZE” => LEVEL3_CACHE_SIZE 268435456
  • Reading /sys/devices/system/cpu/cpu0/cache/index3/size returns 32 MiB, the same as the result from GetLogicalProcessorCacheSizeFromOS from Windows that calls GetLogicalProcessorInformation function (sysinfoapi.h) - Win32 apps | Microsoft Learn.
    • Can be repro’d on the command line using lscpu => L3: 32 MiB (1 instance)

How To Check for the Issue

  1. Get sysconf output: getconf -a | grep "LEVEL"
  2. The full output of lscpu
  3. Check if the L3 (or if available, L4) cache size is the same from sysconf and that from lscpu.
  4. If the values are different, the issue exists.

Solution

  • By default, with no configuration changes, first try to read in the cache information from sysfs and if that fails, fall back to the heuristic we use to compute the value for the ARM* cases.
  • A new configuration DOTNET_GCCacheSizeFromSysConf can be set to 1 to revert to the current behavior i.e., using sysconf to obtain the last level cache.

Performance Testing

Ran with the following GCPerfSim configurations for SVR: -tc 28 -tagb 100 -tlgb 0 -lohar 0-pohar 0 -sohsr 100-4000 -lohsr 102400-204800 -pohsr 100-204800 -sohsi 0 -lohsi 0 -pohsi 0 -sohpi 0 -lohpi 0 -sohfi 0 -lohfi 0 -pohfi 0 -allocType reference -testKind time

image

MetricNot With SysConfWith SysConf
Peak Heap Size (MB)339.4582656.194
% Pause Time in GC39.07.7

Comment threadsrc/coreclr/gc/unix/gcenv.unix.cpp Outdated
@mrsharm
mrsharm marked this pull request as ready for review October 4, 2024 19:19
@mrsharmmrsharm changed the title [Work in Progress] Fix an issue with the last level cache values on Linux running on certain AMD ProcessorsFix an issue with the last level cache values on Linux running on certain AMD ProcessorsOct 4, 2024
Comment threadsrc/coreclr/gc/unix/gcenv.unix.cpp
Comment threadsrc/coreclr/gc/unix/gcenv.unix.cpp Outdated
Comment threadsrc/coreclr/gc/unix/gcenv.unix.cpp Outdated
@Maoni0

Copy link
Copy Markdown
Member

the rest looks okay to me.. would be great if @janvorli could take a look.

@janvorli

Copy link
Copy Markdown
Member

There is one thing I keep thinking about. Would it be a problem in case the /sys/devices/system/cpu/cpu0/cache is not present to still read the size from sysconf? In other words, to let the new config knob control just the order in which we try to use the /sys/devices/system/cpu/cpu0/cache and sysconf? I wonder if in the case the /sys/devices/system/cpu/cpu0/cache is missing, the heuristic fallback would give us a reasonable value.

@Maoni0

Copy link
Copy Markdown
Member

the way I look at this is from the user's POV the values from sysconf is simply incorrect. so it'd be better to just take the heuristic values. another option is to treat sysconf to always give us the full cache sizes and check to see how many cores this process is actually allowed to use and get a ratio (so if sysconf reports 128mb and 64 cores, our process can only use 8 cores, we take 1/8 of 128mb).

@janvorli

janvorli commented Oct 9, 2024

Copy link
Copy Markdown
Member

I would rather avoid introducing this new kind of heuristic, because it depends on the internal topology of the processor. One of the cases we were seeing this issue occurred on some AMD processors, because they have 4 separate 3rd level caches where each one is shared by 1/4 of the cores. In this case, the customer was using the full CPU and still the sysconf was returning a sum of the 3rd level cache sizes, it means 4 times higher value.
So let's keep this change as is.

@mrsharm

Copy link
Copy Markdown
MemberAuthor

How To Check for the Issue

  1. Get sysconf output for the last level cache size: getconf -a | grep "LEVEL"
  2. The full output of lscpu
  3. Check if the last level cache size is the same from sysconf and that from lscpu.
  4. If the values are different, the issue exists.

@mrsharm

Copy link
Copy Markdown
MemberAuthor

/backport to release/9.0-staging

@github-actions

Copy link
Copy Markdown
Contributor

Started backporting to release/9.0-staging: https://github.com/dotnet/runtime/actions/runs/11803383363

@github-actions

Copy link
Copy Markdown
Contributor

@mrsharm backporting to release/9.0-staging failed, the patch most likely resulted in conflicts:

$ git am --3way --empty=keep --ignore-whitespace --keep-non-patch changes.patch
Applying: Started work on the Last Level Cache optimization
.git/rebase-apply/patch:112: trailing whitespace.
#endif 
.git/rebase-apply/patch:152: trailing whitespace.
// It seems ok to set the same default sizes when the cache info isn’t available on the /sys/ path like we did with arm. .git/rebase-apply/patch:166: trailing whitespace.
warning: 3 lines add whitespace errors.
Using index info to reconstruct a base tree...
M	src/coreclr/gc/gcconfig.h
Falling back to patching base and 3-way merge...
Auto-merging src/coreclr/gc/gcconfig.h
CONFLICT (content): Merge conflict in src/coreclr/gc/gcconfig.h
error: Failed to merge in the changes.
hint: Use 'git am --show-current-patch=diff' to see the failed patch
hint: When you have resolved this problem, run "git am --continue".
hint: If you prefer to skip this patch, run "git am --skip" instead.
hint: To restore the original branch and stop patching, run "git am --abort".
hint: Disable this message with "git config advice.mergeConflict false"
Patch failed at 0001 Started work on the Last Level Cache optimization
Error: The process '/usr/bin/git' failed with exit code 128

Please backport manually!

@github-actions

Copy link
Copy Markdown
Contributor

@mrsharm an error occurred while backporting to release/9.0-staging, please check the run log for details!

Error: git am failed, most likely due to a merge conflict.

mikelle-rogers pushed a commit to mikelle-rogers/runtime that referenced this pull request Dec 10, 2024
@github-actionsgithub-actionsBot locked and limited conversation to collaborators Dec 13, 2024
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

GC picks wrong L3 cache size on Linux

3 participants

@mrsharm@Maoni0@janvorli
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Fix an issue with the last level cache values on Linux running on certain AMD Processors - #108492

Merged
mrsharm merged 12 commits into
dotnet:mainfrom
mrsharm:lastlevelcache_refactor
Oct 11, 2024
Merged

Fix an issue with the last level cache values on Linux running on certain AMD Processors#108492
mrsharm merged 12 commits into
dotnet:mainfrom
mrsharm:lastlevelcache_refactor

Conversation

@mrsharm

@mrsharmmrsharm commented Oct 2, 2024

Copy link
Copy Markdown
Member

Fixes: #76290

Problem Details

We recently discovered an issue that affects Unix based VMs where we are taking the host’s (as opposed to the VM’s) for certain AMD processor's last level cache size to be used in the GetLogicalProcessorCacheSizeFromOS call to discern the gen0 budget for both WKS and SVR. This is because sysconf, the method we first try in GetLogicalProcessorCacheSizeFromOS, gets us the last level cache of the host machine as opposed to the fallback code path that reads the value of /sys/devices/system/cpu/cpu0/cache/index{LastLevelCache}/size. Consequently, the gen0 budgets are significantly different between Unix VMs and Windows using certain AMD processors on the same machine and the further implication of this is that we are probably setting much larger value than expected for the Gen0 budget for the GC running on Unix based VMs.

The details from my v16 CPU based DevBox with an AMD EPYC 7763 64 Core Processor running Ubuntu 22.04.3 via WSL are as follows:

  • sysconf returns the last cache size (L3) for the host machine (AMD EPYC™ 7763 – specs are here) as 256 MB.
    • Can be repro’d on the command line using:
      getconf -a | grep “LEVEL3_CACHE_SIZE” => LEVEL3_CACHE_SIZE 268435456
  • Reading /sys/devices/system/cpu/cpu0/cache/index3/size returns 32 MiB, the same as the result from GetLogicalProcessorCacheSizeFromOS from Windows that calls GetLogicalProcessorInformation function (sysinfoapi.h) - Win32 apps | Microsoft Learn.
    • Can be repro’d on the command line using lscpu => L3: 32 MiB (1 instance)

How To Check for the Issue

  1. Get sysconf output: getconf -a | grep "LEVEL"
  2. The full output of lscpu
  3. Check if the L3 (or if available, L4) cache size is the same from sysconf and that from lscpu.
  4. If the values are different, the issue exists.

Solution

  • By default, with no configuration changes, first try to read in the cache information from sysfs and if that fails, fall back to the heuristic we use to compute the value for the ARM* cases.
  • A new configuration DOTNET_GCCacheSizeFromSysConf can be set to 1 to revert to the current behavior i.e., using sysconf to obtain the last level cache.

Performance Testing

Ran with the following GCPerfSim configurations for SVR: -tc 28 -tagb 100 -tlgb 0 -lohar 0-pohar 0 -sohsr 100-4000 -lohsr 102400-204800 -pohsr 100-204800 -sohsi 0 -lohsi 0 -pohsi 0 -sohpi 0 -lohpi 0 -sohfi 0 -lohfi 0 -pohfi 0 -allocType reference -testKind time

image

MetricNot With SysConfWith SysConf
Peak Heap Size (MB)339.4582656.194
% Pause Time in GC39.07.7

Comment threadsrc/coreclr/gc/unix/gcenv.unix.cpp Outdated
@mrsharm
mrsharm marked this pull request as ready for review October 4, 2024 19:19
@mrsharmmrsharm changed the title [Work in Progress] Fix an issue with the last level cache values on Linux running on certain AMD ProcessorsFix an issue with the last level cache values on Linux running on certain AMD ProcessorsOct 4, 2024
Comment threadsrc/coreclr/gc/unix/gcenv.unix.cpp
Comment threadsrc/coreclr/gc/unix/gcenv.unix.cpp Outdated
Comment threadsrc/coreclr/gc/unix/gcenv.unix.cpp Outdated
@Maoni0

Copy link
Copy Markdown
Member

the rest looks okay to me.. would be great if @janvorli could take a look.

@janvorli

Copy link
Copy Markdown
Member

There is one thing I keep thinking about. Would it be a problem in case the /sys/devices/system/cpu/cpu0/cache is not present to still read the size from sysconf? In other words, to let the new config knob control just the order in which we try to use the /sys/devices/system/cpu/cpu0/cache and sysconf? I wonder if in the case the /sys/devices/system/cpu/cpu0/cache is missing, the heuristic fallback would give us a reasonable value.

@Maoni0

Copy link
Copy Markdown
Member

the way I look at this is from the user's POV the values from sysconf is simply incorrect. so it'd be better to just take the heuristic values. another option is to treat sysconf to always give us the full cache sizes and check to see how many cores this process is actually allowed to use and get a ratio (so if sysconf reports 128mb and 64 cores, our process can only use 8 cores, we take 1/8 of 128mb).

@janvorli

janvorli commented Oct 9, 2024

Copy link
Copy Markdown
Member

I would rather avoid introducing this new kind of heuristic, because it depends on the internal topology of the processor. One of the cases we were seeing this issue occurred on some AMD processors, because they have 4 separate 3rd level caches where each one is shared by 1/4 of the cores. In this case, the customer was using the full CPU and still the sysconf was returning a sum of the 3rd level cache sizes, it means 4 times higher value.
So let's keep this change as is.

@mrsharm

Copy link
Copy Markdown
MemberAuthor

How To Check for the Issue

  1. Get sysconf output for the last level cache size: getconf -a | grep "LEVEL"
  2. The full output of lscpu
  3. Check if the last level cache size is the same from sysconf and that from lscpu.
  4. If the values are different, the issue exists.

@mrsharm

Copy link
Copy Markdown
MemberAuthor

/backport to release/9.0-staging

@github-actions

Copy link
Copy Markdown
Contributor

Started backporting to release/9.0-staging: https://github.com/dotnet/runtime/actions/runs/11803383363

@github-actions

Copy link
Copy Markdown
Contributor

@mrsharm backporting to release/9.0-staging failed, the patch most likely resulted in conflicts:

$ git am --3way --empty=keep --ignore-whitespace --keep-non-patch changes.patch
Applying: Started work on the Last Level Cache optimization
.git/rebase-apply/patch:112: trailing whitespace.
#endif 
.git/rebase-apply/patch:152: trailing whitespace.
// It seems ok to set the same default sizes when the cache info isn’t available on the /sys/ path like we did with arm. .git/rebase-apply/patch:166: trailing whitespace.
warning: 3 lines add whitespace errors.
Using index info to reconstruct a base tree...
M	src/coreclr/gc/gcconfig.h
Falling back to patching base and 3-way merge...
Auto-merging src/coreclr/gc/gcconfig.h
CONFLICT (content): Merge conflict in src/coreclr/gc/gcconfig.h
error: Failed to merge in the changes.
hint: Use 'git am --show-current-patch=diff' to see the failed patch
hint: When you have resolved this problem, run "git am --continue".
hint: If you prefer to skip this patch, run "git am --skip" instead.
hint: To restore the original branch and stop patching, run "git am --abort".
hint: Disable this message with "git config advice.mergeConflict false"
Patch failed at 0001 Started work on the Last Level Cache optimization
Error: The process '/usr/bin/git' failed with exit code 128

Please backport manually!

@github-actions

Copy link
Copy Markdown
Contributor

@mrsharm an error occurred while backporting to release/9.0-staging, please check the run log for details!

Error: git am failed, most likely due to a merge conflict.

mikelle-rogers pushed a commit to mikelle-rogers/runtime that referenced this pull request Dec 10, 2024
@github-actionsgithub-actionsBot locked and limited conversation to collaborators Dec 13, 2024
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

GC picks wrong L3 cache size on Linux

3 participants

@mrsharm@Maoni0@janvorli
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

Fix an issue with the last level cache values on Linux running on certain AMD Processors - #108492

Merged
mrsharm merged 12 commits into
dotnet:mainfrom
mrsharm:lastlevelcache_refactor
Oct 11, 2024
Merged

Fix an issue with the last level cache values on Linux running on certain AMD Processors#108492
mrsharm merged 12 commits into
dotnet:mainfrom
mrsharm:lastlevelcache_refactor

Conversation

@mrsharm

@mrsharmmrsharm commented Oct 2, 2024

Copy link
Copy Markdown
Member

Fixes: #76290

Problem Details

We recently discovered an issue that affects Unix based VMs where we are taking the host’s (as opposed to the VM’s) for certain AMD processor's last level cache size to be used in the GetLogicalProcessorCacheSizeFromOS call to discern the gen0 budget for both WKS and SVR. This is because sysconf, the method we first try in GetLogicalProcessorCacheSizeFromOS, gets us the last level cache of the host machine as opposed to the fallback code path that reads the value of /sys/devices/system/cpu/cpu0/cache/index{LastLevelCache}/size. Consequently, the gen0 budgets are significantly different between Unix VMs and Windows using certain AMD processors on the same machine and the further implication of this is that we are probably setting much larger value than expected for the Gen0 budget for the GC running on Unix based VMs.

The details from my v16 CPU based DevBox with an AMD EPYC 7763 64 Core Processor running Ubuntu 22.04.3 via WSL are as follows:

  • sysconf returns the last cache size (L3) for the host machine (AMD EPYC™ 7763 – specs are here) as 256 MB.
    • Can be repro’d on the command line using:
      getconf -a | grep “LEVEL3_CACHE_SIZE” => LEVEL3_CACHE_SIZE 268435456
  • Reading /sys/devices/system/cpu/cpu0/cache/index3/size returns 32 MiB, the same as the result from GetLogicalProcessorCacheSizeFromOS from Windows that calls GetLogicalProcessorInformation function (sysinfoapi.h) - Win32 apps | Microsoft Learn.
    • Can be repro’d on the command line using lscpu => L3: 32 MiB (1 instance)

How To Check for the Issue

  1. Get sysconf output: getconf -a | grep "LEVEL"
  2. The full output of lscpu
  3. Check if the L3 (or if available, L4) cache size is the same from sysconf and that from lscpu.
  4. If the values are different, the issue exists.

Solution

  • By default, with no configuration changes, first try to read in the cache information from sysfs and if that fails, fall back to the heuristic we use to compute the value for the ARM* cases.
  • A new configuration DOTNET_GCCacheSizeFromSysConf can be set to 1 to revert to the current behavior i.e., using sysconf to obtain the last level cache.

Performance Testing

Ran with the following GCPerfSim configurations for SVR: -tc 28 -tagb 100 -tlgb 0 -lohar 0-pohar 0 -sohsr 100-4000 -lohsr 102400-204800 -pohsr 100-204800 -sohsi 0 -lohsi 0 -pohsi 0 -sohpi 0 -lohpi 0 -sohfi 0 -lohfi 0 -pohfi 0 -allocType reference -testKind time

image

MetricNot With SysConfWith SysConf
Peak Heap Size (MB)339.4582656.194
% Pause Time in GC39.07.7

Comment threadsrc/coreclr/gc/unix/gcenv.unix.cpp Outdated
@mrsharm
mrsharm marked this pull request as ready for review October 4, 2024 19:19
@mrsharmmrsharm changed the title [Work in Progress] Fix an issue with the last level cache values on Linux running on certain AMD ProcessorsFix an issue with the last level cache values on Linux running on certain AMD ProcessorsOct 4, 2024
Comment threadsrc/coreclr/gc/unix/gcenv.unix.cpp
Comment threadsrc/coreclr/gc/unix/gcenv.unix.cpp Outdated
Comment threadsrc/coreclr/gc/unix/gcenv.unix.cpp Outdated
@Maoni0

Copy link
Copy Markdown
Member

the rest looks okay to me.. would be great if @janvorli could take a look.

@janvorli

Copy link
Copy Markdown
Member

There is one thing I keep thinking about. Would it be a problem in case the /sys/devices/system/cpu/cpu0/cache is not present to still read the size from sysconf? In other words, to let the new config knob control just the order in which we try to use the /sys/devices/system/cpu/cpu0/cache and sysconf? I wonder if in the case the /sys/devices/system/cpu/cpu0/cache is missing, the heuristic fallback would give us a reasonable value.

@Maoni0

Copy link
Copy Markdown
Member

the way I look at this is from the user's POV the values from sysconf is simply incorrect. so it'd be better to just take the heuristic values. another option is to treat sysconf to always give us the full cache sizes and check to see how many cores this process is actually allowed to use and get a ratio (so if sysconf reports 128mb and 64 cores, our process can only use 8 cores, we take 1/8 of 128mb).

@janvorli

janvorli commented Oct 9, 2024

Copy link
Copy Markdown
Member

I would rather avoid introducing this new kind of heuristic, because it depends on the internal topology of the processor. One of the cases we were seeing this issue occurred on some AMD processors, because they have 4 separate 3rd level caches where each one is shared by 1/4 of the cores. In this case, the customer was using the full CPU and still the sysconf was returning a sum of the 3rd level cache sizes, it means 4 times higher value.
So let's keep this change as is.

@mrsharm

Copy link
Copy Markdown
MemberAuthor

How To Check for the Issue

  1. Get sysconf output for the last level cache size: getconf -a | grep "LEVEL"
  2. The full output of lscpu
  3. Check if the last level cache size is the same from sysconf and that from lscpu.
  4. If the values are different, the issue exists.

@mrsharm

Copy link
Copy Markdown
MemberAuthor

/backport to release/9.0-staging

@github-actions

Copy link
Copy Markdown
Contributor

Started backporting to release/9.0-staging: https://github.com/dotnet/runtime/actions/runs/11803383363

@github-actions

Copy link
Copy Markdown
Contributor

@mrsharm backporting to release/9.0-staging failed, the patch most likely resulted in conflicts:

$ git am --3way --empty=keep --ignore-whitespace --keep-non-patch changes.patch
Applying: Started work on the Last Level Cache optimization
.git/rebase-apply/patch:112: trailing whitespace.
#endif 
.git/rebase-apply/patch:152: trailing whitespace.
// It seems ok to set the same default sizes when the cache info isn’t available on the /sys/ path like we did with arm. .git/rebase-apply/patch:166: trailing whitespace.
warning: 3 lines add whitespace errors.
Using index info to reconstruct a base tree...
M	src/coreclr/gc/gcconfig.h
Falling back to patching base and 3-way merge...
Auto-merging src/coreclr/gc/gcconfig.h
CONFLICT (content): Merge conflict in src/coreclr/gc/gcconfig.h
error: Failed to merge in the changes.
hint: Use 'git am --show-current-patch=diff' to see the failed patch
hint: When you have resolved this problem, run "git am --continue".
hint: If you prefer to skip this patch, run "git am --skip" instead.
hint: To restore the original branch and stop patching, run "git am --abort".
hint: Disable this message with "git config advice.mergeConflict false"
Patch failed at 0001 Started work on the Last Level Cache optimization
Error: The process '/usr/bin/git' failed with exit code 128

Please backport manually!

@github-actions

Copy link
Copy Markdown
Contributor

@mrsharm an error occurred while backporting to release/9.0-staging, please check the run log for details!

Error: git am failed, most likely due to a merge conflict.

mikelle-rogers pushed a commit to mikelle-rogers/runtime that referenced this pull request Dec 10, 2024
@github-actionsgithub-actionsBot locked and limited conversation to collaborators Dec 13, 2024
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

GC picks wrong L3 cache size on Linux

3 participants

@mrsharm@Maoni0@janvorli
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Fix an issue with the last level cache values on Linux running on certain AMD Processors - #108492

Merged
mrsharm merged 12 commits into
dotnet:mainfrom
mrsharm:lastlevelcache_refactor
Oct 11, 2024
Merged

Fix an issue with the last level cache values on Linux running on certain AMD Processors#108492
mrsharm merged 12 commits into
dotnet:mainfrom
mrsharm:lastlevelcache_refactor

Conversation

@mrsharm

@mrsharmmrsharm commented Oct 2, 2024

Copy link
Copy Markdown
Member

Fixes: #76290

Problem Details

We recently discovered an issue that affects Unix based VMs where we are taking the host’s (as opposed to the VM’s) for certain AMD processor's last level cache size to be used in the GetLogicalProcessorCacheSizeFromOS call to discern the gen0 budget for both WKS and SVR. This is because sysconf, the method we first try in GetLogicalProcessorCacheSizeFromOS, gets us the last level cache of the host machine as opposed to the fallback code path that reads the value of /sys/devices/system/cpu/cpu0/cache/index{LastLevelCache}/size. Consequently, the gen0 budgets are significantly different between Unix VMs and Windows using certain AMD processors on the same machine and the further implication of this is that we are probably setting much larger value than expected for the Gen0 budget for the GC running on Unix based VMs.

The details from my v16 CPU based DevBox with an AMD EPYC 7763 64 Core Processor running Ubuntu 22.04.3 via WSL are as follows:

  • sysconf returns the last cache size (L3) for the host machine (AMD EPYC™ 7763 – specs are here) as 256 MB.
    • Can be repro’d on the command line using:
      getconf -a | grep “LEVEL3_CACHE_SIZE” => LEVEL3_CACHE_SIZE 268435456
  • Reading /sys/devices/system/cpu/cpu0/cache/index3/size returns 32 MiB, the same as the result from GetLogicalProcessorCacheSizeFromOS from Windows that calls GetLogicalProcessorInformation function (sysinfoapi.h) - Win32 apps | Microsoft Learn.
    • Can be repro’d on the command line using lscpu => L3: 32 MiB (1 instance)

How To Check for the Issue

  1. Get sysconf output: getconf -a | grep "LEVEL"
  2. The full output of lscpu
  3. Check if the L3 (or if available, L4) cache size is the same from sysconf and that from lscpu.
  4. If the values are different, the issue exists.

Solution

  • By default, with no configuration changes, first try to read in the cache information from sysfs and if that fails, fall back to the heuristic we use to compute the value for the ARM* cases.
  • A new configuration DOTNET_GCCacheSizeFromSysConf can be set to 1 to revert to the current behavior i.e., using sysconf to obtain the last level cache.

Performance Testing

Ran with the following GCPerfSim configurations for SVR: -tc 28 -tagb 100 -tlgb 0 -lohar 0-pohar 0 -sohsr 100-4000 -lohsr 102400-204800 -pohsr 100-204800 -sohsi 0 -lohsi 0 -pohsi 0 -sohpi 0 -lohpi 0 -sohfi 0 -lohfi 0 -pohfi 0 -allocType reference -testKind time

image

MetricNot With SysConfWith SysConf
Peak Heap Size (MB)339.4582656.194
% Pause Time in GC39.07.7

Comment threadsrc/coreclr/gc/unix/gcenv.unix.cpp Outdated
@mrsharm
mrsharm marked this pull request as ready for review October 4, 2024 19:19
@mrsharmmrsharm changed the title [Work in Progress] Fix an issue with the last level cache values on Linux running on certain AMD ProcessorsFix an issue with the last level cache values on Linux running on certain AMD ProcessorsOct 4, 2024
Comment threadsrc/coreclr/gc/unix/gcenv.unix.cpp
Comment threadsrc/coreclr/gc/unix/gcenv.unix.cpp Outdated
Comment threadsrc/coreclr/gc/unix/gcenv.unix.cpp Outdated
@Maoni0

Copy link
Copy Markdown
Member

the rest looks okay to me.. would be great if @janvorli could take a look.

@janvorli

Copy link
Copy Markdown
Member

There is one thing I keep thinking about. Would it be a problem in case the /sys/devices/system/cpu/cpu0/cache is not present to still read the size from sysconf? In other words, to let the new config knob control just the order in which we try to use the /sys/devices/system/cpu/cpu0/cache and sysconf? I wonder if in the case the /sys/devices/system/cpu/cpu0/cache is missing, the heuristic fallback would give us a reasonable value.

@Maoni0

Copy link
Copy Markdown
Member

the way I look at this is from the user's POV the values from sysconf is simply incorrect. so it'd be better to just take the heuristic values. another option is to treat sysconf to always give us the full cache sizes and check to see how many cores this process is actually allowed to use and get a ratio (so if sysconf reports 128mb and 64 cores, our process can only use 8 cores, we take 1/8 of 128mb).

@janvorli

janvorli commented Oct 9, 2024

Copy link
Copy Markdown
Member

I would rather avoid introducing this new kind of heuristic, because it depends on the internal topology of the processor. One of the cases we were seeing this issue occurred on some AMD processors, because they have 4 separate 3rd level caches where each one is shared by 1/4 of the cores. In this case, the customer was using the full CPU and still the sysconf was returning a sum of the 3rd level cache sizes, it means 4 times higher value.
So let's keep this change as is.

@mrsharm

Copy link
Copy Markdown
MemberAuthor

How To Check for the Issue

  1. Get sysconf output for the last level cache size: getconf -a | grep "LEVEL"
  2. The full output of lscpu
  3. Check if the last level cache size is the same from sysconf and that from lscpu.
  4. If the values are different, the issue exists.

@mrsharm

Copy link
Copy Markdown
MemberAuthor

/backport to release/9.0-staging

@github-actions

Copy link
Copy Markdown
Contributor

Started backporting to release/9.0-staging: https://github.com/dotnet/runtime/actions/runs/11803383363

@github-actions

Copy link
Copy Markdown
Contributor

@mrsharm backporting to release/9.0-staging failed, the patch most likely resulted in conflicts:

$ git am --3way --empty=keep --ignore-whitespace --keep-non-patch changes.patch
Applying: Started work on the Last Level Cache optimization
.git/rebase-apply/patch:112: trailing whitespace.
#endif 
.git/rebase-apply/patch:152: trailing whitespace.
// It seems ok to set the same default sizes when the cache info isn’t available on the /sys/ path like we did with arm. .git/rebase-apply/patch:166: trailing whitespace.
warning: 3 lines add whitespace errors.
Using index info to reconstruct a base tree...
M	src/coreclr/gc/gcconfig.h
Falling back to patching base and 3-way merge...
Auto-merging src/coreclr/gc/gcconfig.h
CONFLICT (content): Merge conflict in src/coreclr/gc/gcconfig.h
error: Failed to merge in the changes.
hint: Use 'git am --show-current-patch=diff' to see the failed patch
hint: When you have resolved this problem, run "git am --continue".
hint: If you prefer to skip this patch, run "git am --skip" instead.
hint: To restore the original branch and stop patching, run "git am --abort".
hint: Disable this message with "git config advice.mergeConflict false"
Patch failed at 0001 Started work on the Last Level Cache optimization
Error: The process '/usr/bin/git' failed with exit code 128

Please backport manually!

@github-actions

Copy link
Copy Markdown
Contributor

@mrsharm an error occurred while backporting to release/9.0-staging, please check the run log for details!

Error: git am failed, most likely due to a merge conflict.

mikelle-rogers pushed a commit to mikelle-rogers/runtime that referenced this pull request Dec 10, 2024
@github-actionsgithub-actionsBot locked and limited conversation to collaborators Dec 13, 2024
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

GC picks wrong L3 cache size on Linux

3 participants

@mrsharm@Maoni0@janvorli
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Fix an issue with the last level cache values on Linux running on certain AMD Processors - #108492

Merged
mrsharm merged 12 commits into
dotnet:mainfrom
mrsharm:lastlevelcache_refactor
Oct 11, 2024
Merged

Fix an issue with the last level cache values on Linux running on certain AMD Processors#108492
mrsharm merged 12 commits into
dotnet:mainfrom
mrsharm:lastlevelcache_refactor

Conversation

@mrsharm

@mrsharmmrsharm commented Oct 2, 2024

Copy link
Copy Markdown
Member

Fixes: #76290

Problem Details

We recently discovered an issue that affects Unix based VMs where we are taking the host’s (as opposed to the VM’s) for certain AMD processor's last level cache size to be used in the GetLogicalProcessorCacheSizeFromOS call to discern the gen0 budget for both WKS and SVR. This is because sysconf, the method we first try in GetLogicalProcessorCacheSizeFromOS, gets us the last level cache of the host machine as opposed to the fallback code path that reads the value of /sys/devices/system/cpu/cpu0/cache/index{LastLevelCache}/size. Consequently, the gen0 budgets are significantly different between Unix VMs and Windows using certain AMD processors on the same machine and the further implication of this is that we are probably setting much larger value than expected for the Gen0 budget for the GC running on Unix based VMs.

The details from my v16 CPU based DevBox with an AMD EPYC 7763 64 Core Processor running Ubuntu 22.04.3 via WSL are as follows:

  • sysconf returns the last cache size (L3) for the host machine (AMD EPYC™ 7763 – specs are here) as 256 MB.
    • Can be repro’d on the command line using:
      getconf -a | grep “LEVEL3_CACHE_SIZE” => LEVEL3_CACHE_SIZE 268435456
  • Reading /sys/devices/system/cpu/cpu0/cache/index3/size returns 32 MiB, the same as the result from GetLogicalProcessorCacheSizeFromOS from Windows that calls GetLogicalProcessorInformation function (sysinfoapi.h) - Win32 apps | Microsoft Learn.
    • Can be repro’d on the command line using lscpu => L3: 32 MiB (1 instance)

How To Check for the Issue

  1. Get sysconf output: getconf -a | grep "LEVEL"
  2. The full output of lscpu
  3. Check if the L3 (or if available, L4) cache size is the same from sysconf and that from lscpu.
  4. If the values are different, the issue exists.

Solution

  • By default, with no configuration changes, first try to read in the cache information from sysfs and if that fails, fall back to the heuristic we use to compute the value for the ARM* cases.
  • A new configuration DOTNET_GCCacheSizeFromSysConf can be set to 1 to revert to the current behavior i.e., using sysconf to obtain the last level cache.

Performance Testing

Ran with the following GCPerfSim configurations for SVR: -tc 28 -tagb 100 -tlgb 0 -lohar 0-pohar 0 -sohsr 100-4000 -lohsr 102400-204800 -pohsr 100-204800 -sohsi 0 -lohsi 0 -pohsi 0 -sohpi 0 -lohpi 0 -sohfi 0 -lohfi 0 -pohfi 0 -allocType reference -testKind time

image

MetricNot With SysConfWith SysConf
Peak Heap Size (MB)339.4582656.194
% Pause Time in GC39.07.7

Comment threadsrc/coreclr/gc/unix/gcenv.unix.cpp Outdated
@mrsharm
mrsharm marked this pull request as ready for review October 4, 2024 19:19
@mrsharmmrsharm changed the title [Work in Progress] Fix an issue with the last level cache values on Linux running on certain AMD ProcessorsFix an issue with the last level cache values on Linux running on certain AMD ProcessorsOct 4, 2024
Comment threadsrc/coreclr/gc/unix/gcenv.unix.cpp
Comment threadsrc/coreclr/gc/unix/gcenv.unix.cpp Outdated
Comment threadsrc/coreclr/gc/unix/gcenv.unix.cpp Outdated
@Maoni0

Copy link
Copy Markdown
Member

the rest looks okay to me.. would be great if @janvorli could take a look.

@janvorli

Copy link
Copy Markdown
Member

There is one thing I keep thinking about. Would it be a problem in case the /sys/devices/system/cpu/cpu0/cache is not present to still read the size from sysconf? In other words, to let the new config knob control just the order in which we try to use the /sys/devices/system/cpu/cpu0/cache and sysconf? I wonder if in the case the /sys/devices/system/cpu/cpu0/cache is missing, the heuristic fallback would give us a reasonable value.

@Maoni0

Copy link
Copy Markdown
Member

the way I look at this is from the user's POV the values from sysconf is simply incorrect. so it'd be better to just take the heuristic values. another option is to treat sysconf to always give us the full cache sizes and check to see how many cores this process is actually allowed to use and get a ratio (so if sysconf reports 128mb and 64 cores, our process can only use 8 cores, we take 1/8 of 128mb).

@janvorli

janvorli commented Oct 9, 2024

Copy link
Copy Markdown
Member

I would rather avoid introducing this new kind of heuristic, because it depends on the internal topology of the processor. One of the cases we were seeing this issue occurred on some AMD processors, because they have 4 separate 3rd level caches where each one is shared by 1/4 of the cores. In this case, the customer was using the full CPU and still the sysconf was returning a sum of the 3rd level cache sizes, it means 4 times higher value.
So let's keep this change as is.

@mrsharm

Copy link
Copy Markdown
MemberAuthor

How To Check for the Issue

  1. Get sysconf output for the last level cache size: getconf -a | grep "LEVEL"
  2. The full output of lscpu
  3. Check if the last level cache size is the same from sysconf and that from lscpu.
  4. If the values are different, the issue exists.

@mrsharm

Copy link
Copy Markdown
MemberAuthor

/backport to release/9.0-staging

@github-actions

Copy link
Copy Markdown
Contributor

Started backporting to release/9.0-staging: https://github.com/dotnet/runtime/actions/runs/11803383363

@github-actions

Copy link
Copy Markdown
Contributor

@mrsharm backporting to release/9.0-staging failed, the patch most likely resulted in conflicts:

$ git am --3way --empty=keep --ignore-whitespace --keep-non-patch changes.patch
Applying: Started work on the Last Level Cache optimization
.git/rebase-apply/patch:112: trailing whitespace.
#endif 
.git/rebase-apply/patch:152: trailing whitespace.
// It seems ok to set the same default sizes when the cache info isn’t available on the /sys/ path like we did with arm. .git/rebase-apply/patch:166: trailing whitespace.
warning: 3 lines add whitespace errors.
Using index info to reconstruct a base tree...
M	src/coreclr/gc/gcconfig.h
Falling back to patching base and 3-way merge...
Auto-merging src/coreclr/gc/gcconfig.h
CONFLICT (content): Merge conflict in src/coreclr/gc/gcconfig.h
error: Failed to merge in the changes.
hint: Use 'git am --show-current-patch=diff' to see the failed patch
hint: When you have resolved this problem, run "git am --continue".
hint: If you prefer to skip this patch, run "git am --skip" instead.
hint: To restore the original branch and stop patching, run "git am --abort".
hint: Disable this message with "git config advice.mergeConflict false"
Patch failed at 0001 Started work on the Last Level Cache optimization
Error: The process '/usr/bin/git' failed with exit code 128

Please backport manually!

@github-actions

Copy link
Copy Markdown
Contributor

@mrsharm an error occurred while backporting to release/9.0-staging, please check the run log for details!

Error: git am failed, most likely due to a merge conflict.

mikelle-rogers pushed a commit to mikelle-rogers/runtime that referenced this pull request Dec 10, 2024
@github-actionsgithub-actionsBot locked and limited conversation to collaborators Dec 13, 2024
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

GC picks wrong L3 cache size on Linux

3 participants

@mrsharm@Maoni0@janvorli
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

Fix an issue with the last level cache values on Linux running on certain AMD Processors - #108492

Merged
mrsharm merged 12 commits into
dotnet:mainfrom
mrsharm:lastlevelcache_refactor
Oct 11, 2024
Merged

Fix an issue with the last level cache values on Linux running on certain AMD Processors#108492
mrsharm merged 12 commits into
dotnet:mainfrom
mrsharm:lastlevelcache_refactor

Conversation

@mrsharm

@mrsharmmrsharm commented Oct 2, 2024

Copy link
Copy Markdown
Member

Fixes: #76290

Problem Details

We recently discovered an issue that affects Unix based VMs where we are taking the host’s (as opposed to the VM’s) for certain AMD processor's last level cache size to be used in the GetLogicalProcessorCacheSizeFromOS call to discern the gen0 budget for both WKS and SVR. This is because sysconf, the method we first try in GetLogicalProcessorCacheSizeFromOS, gets us the last level cache of the host machine as opposed to the fallback code path that reads the value of /sys/devices/system/cpu/cpu0/cache/index{LastLevelCache}/size. Consequently, the gen0 budgets are significantly different between Unix VMs and Windows using certain AMD processors on the same machine and the further implication of this is that we are probably setting much larger value than expected for the Gen0 budget for the GC running on Unix based VMs.

The details from my v16 CPU based DevBox with an AMD EPYC 7763 64 Core Processor running Ubuntu 22.04.3 via WSL are as follows:

  • sysconf returns the last cache size (L3) for the host machine (AMD EPYC™ 7763 – specs are here) as 256 MB.
    • Can be repro’d on the command line using:
      getconf -a | grep “LEVEL3_CACHE_SIZE” => LEVEL3_CACHE_SIZE 268435456
  • Reading /sys/devices/system/cpu/cpu0/cache/index3/size returns 32 MiB, the same as the result from GetLogicalProcessorCacheSizeFromOS from Windows that calls GetLogicalProcessorInformation function (sysinfoapi.h) - Win32 apps | Microsoft Learn.
    • Can be repro’d on the command line using lscpu => L3: 32 MiB (1 instance)

How To Check for the Issue

  1. Get sysconf output: getconf -a | grep "LEVEL"
  2. The full output of lscpu
  3. Check if the L3 (or if available, L4) cache size is the same from sysconf and that from lscpu.
  4. If the values are different, the issue exists.

Solution

  • By default, with no configuration changes, first try to read in the cache information from sysfs and if that fails, fall back to the heuristic we use to compute the value for the ARM* cases.
  • A new configuration DOTNET_GCCacheSizeFromSysConf can be set to 1 to revert to the current behavior i.e., using sysconf to obtain the last level cache.

Performance Testing

Ran with the following GCPerfSim configurations for SVR: -tc 28 -tagb 100 -tlgb 0 -lohar 0-pohar 0 -sohsr 100-4000 -lohsr 102400-204800 -pohsr 100-204800 -sohsi 0 -lohsi 0 -pohsi 0 -sohpi 0 -lohpi 0 -sohfi 0 -lohfi 0 -pohfi 0 -allocType reference -testKind time

image

MetricNot With SysConfWith SysConf
Peak Heap Size (MB)339.4582656.194
% Pause Time in GC39.07.7

Comment threadsrc/coreclr/gc/unix/gcenv.unix.cpp Outdated
@mrsharm
mrsharm marked this pull request as ready for review October 4, 2024 19:19
@mrsharmmrsharm changed the title [Work in Progress] Fix an issue with the last level cache values on Linux running on certain AMD ProcessorsFix an issue with the last level cache values on Linux running on certain AMD ProcessorsOct 4, 2024
Comment threadsrc/coreclr/gc/unix/gcenv.unix.cpp
Comment threadsrc/coreclr/gc/unix/gcenv.unix.cpp Outdated
Comment threadsrc/coreclr/gc/unix/gcenv.unix.cpp Outdated
@Maoni0

Copy link
Copy Markdown
Member

the rest looks okay to me.. would be great if @janvorli could take a look.

@janvorli

Copy link
Copy Markdown
Member

There is one thing I keep thinking about. Would it be a problem in case the /sys/devices/system/cpu/cpu0/cache is not present to still read the size from sysconf? In other words, to let the new config knob control just the order in which we try to use the /sys/devices/system/cpu/cpu0/cache and sysconf? I wonder if in the case the /sys/devices/system/cpu/cpu0/cache is missing, the heuristic fallback would give us a reasonable value.

@Maoni0

Copy link
Copy Markdown
Member

the way I look at this is from the user's POV the values from sysconf is simply incorrect. so it'd be better to just take the heuristic values. another option is to treat sysconf to always give us the full cache sizes and check to see how many cores this process is actually allowed to use and get a ratio (so if sysconf reports 128mb and 64 cores, our process can only use 8 cores, we take 1/8 of 128mb).

@janvorli

janvorli commented Oct 9, 2024

Copy link
Copy Markdown
Member

I would rather avoid introducing this new kind of heuristic, because it depends on the internal topology of the processor. One of the cases we were seeing this issue occurred on some AMD processors, because they have 4 separate 3rd level caches where each one is shared by 1/4 of the cores. In this case, the customer was using the full CPU and still the sysconf was returning a sum of the 3rd level cache sizes, it means 4 times higher value.
So let's keep this change as is.

@mrsharm

Copy link
Copy Markdown
MemberAuthor

How To Check for the Issue

  1. Get sysconf output for the last level cache size: getconf -a | grep "LEVEL"
  2. The full output of lscpu
  3. Check if the last level cache size is the same from sysconf and that from lscpu.
  4. If the values are different, the issue exists.

@mrsharm

Copy link
Copy Markdown
MemberAuthor

/backport to release/9.0-staging

@github-actions

Copy link
Copy Markdown
Contributor

Started backporting to release/9.0-staging: https://github.com/dotnet/runtime/actions/runs/11803383363

@github-actions

Copy link
Copy Markdown
Contributor

@mrsharm backporting to release/9.0-staging failed, the patch most likely resulted in conflicts:

$ git am --3way --empty=keep --ignore-whitespace --keep-non-patch changes.patch
Applying: Started work on the Last Level Cache optimization
.git/rebase-apply/patch:112: trailing whitespace.
#endif 
.git/rebase-apply/patch:152: trailing whitespace.
// It seems ok to set the same default sizes when the cache info isn’t available on the /sys/ path like we did with arm. .git/rebase-apply/patch:166: trailing whitespace.
warning: 3 lines add whitespace errors.
Using index info to reconstruct a base tree...
M	src/coreclr/gc/gcconfig.h
Falling back to patching base and 3-way merge...
Auto-merging src/coreclr/gc/gcconfig.h
CONFLICT (content): Merge conflict in src/coreclr/gc/gcconfig.h
error: Failed to merge in the changes.
hint: Use 'git am --show-current-patch=diff' to see the failed patch
hint: When you have resolved this problem, run "git am --continue".
hint: If you prefer to skip this patch, run "git am --skip" instead.
hint: To restore the original branch and stop patching, run "git am --abort".
hint: Disable this message with "git config advice.mergeConflict false"
Patch failed at 0001 Started work on the Last Level Cache optimization
Error: The process '/usr/bin/git' failed with exit code 128

Please backport manually!

@github-actions

Copy link
Copy Markdown
Contributor

@mrsharm an error occurred while backporting to release/9.0-staging, please check the run log for details!

Error: git am failed, most likely due to a merge conflict.

mikelle-rogers pushed a commit to mikelle-rogers/runtime that referenced this pull request Dec 10, 2024
@github-actionsgithub-actionsBot locked and limited conversation to collaborators Dec 13, 2024
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

GC picks wrong L3 cache size on Linux

3 participants

@mrsharm@Maoni0@janvorli