Remove hard_limit_for_bookkeeping - #77480

Merged
PeterSolMS merged 5 commits into
dotnet:mainfrom
PeterSolMS:Remove_hard_limit_for_bookkeeping
Dec 12, 2022
Merged

Remove hard_limit_for_bookkeeping#77480
PeterSolMS merged 5 commits into
dotnet:mainfrom
PeterSolMS:Remove_hard_limit_for_bookkeeping

Conversation

@PeterSolMS

Copy link
Copy Markdown
Contributor

As it turns out, it's not so easy to set aside a hard limit for the GC's bookkeeping, because some regions will be partially comitted and so will need more bookkeeping information as a percentage.

So this removes the hard_limit_for_bookkeeping and associated fields, and instead commits memory for the mark array eagerly, even if BGC is not in progress.

…C's bookkeeping, because some regions will be partially comitted and so will need more bookkeeping information as a percentage.
So this removes the hard_limit_for_bookkeeping and associated fields, and instead commits memory for the mark array eagerly, even if BGC is not in progress.
@ghost

Copy link
Copy Markdown

Tagging subscribers to this area: @dotnet/gc
See info in area-owners.md if you want to be subscribed.

Issue Details

As it turns out, it's not so easy to set aside a hard limit for the GC's bookkeeping, because some regions will be partially comitted and so will need more bookkeeping information as a percentage.

So this removes the hard_limit_for_bookkeeping and associated fields, and instead commits memory for the mark array eagerly, even if BGC is not in progress.

Author:PeterSolMS
Assignees:PeterSolMS
Labels:

area-GC-coreclr

Milestone:-

@cshungcshung left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I liked this idea more than trying to set aside memory for bookkeeping. The one thing I am not sure about is that now we are committing the mark array for every region. If background GC is happening anyway, it might be fine because we will be committing them anyway, but what if we don't?

Comment threadsrc/coreclr/gc/gcpriv.h
Comment threadsrc/coreclr/gc/gc.cpp
dprintf (GC_TABLE_LOG, ("new seg %Ix, mark_array is %Ix",
heap_segment_mem (region), mark_array));
if (((region->flags & heap_segment_flags_ma_committed) == 0) &&
!commit_mark_array_new_seg (__this, region))

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Shall we guard this under gc_can_use_concurrent?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

commit_mark_array_new_seg shouldn't do anything if concurrent is disabled; although I'm looking at the code, we are not initializing background_saved_highest_address in init_gc_heap which we should. @PeterSolMS could you please add this (ie, init background_saved_highest_address and background_saved_lowest_address to 0 in init_gc_heap like we do with WKS GC)? we could still guard this with gc_can_use_concurrent just to indicate our intention but it's not essential.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

I just pushed changes with the initialization of background_saved_lowest_address and background_saved_highest_address, and the restoration of current_total_committed_bookkeeping.

@Maoni0

Copy link
Copy Markdown
Member

If background GC is happening anyway, it might be fine because we will be committing them anyway, but what if we don't?

that is the drawback with doing this. but if concurrent GC is enabled, it's very likely we'll need to do a BGC at some point so it's not too bad.

…ments back.
Initialize background_saved_lowest_address and background_saved_lowest_address.
Removed unrelated bug fix which is addressed by a separate PR.
@PeterSolMS

Copy link
Copy Markdown
ContributorAuthor

I think I found a hole in our logic - clear_region_info (called by return_free_region) will decommit the mark array in high memory load. When get_free_region tries to commit again, we'll fail and get the same AV as before. Perhaps this means we'll have to keep the mark array committed, i.e. disable the logic to decommit the mark array in high memory load?

…info.
The issue is that GC needs at least one free region, and it needs the mark array committed. So when it tries to get a region at the end, and we cannot commit the mark array, we cannot actually get a free region. Currently we AV in this case, but there really isn't a good option to recover at this point. So it's better to keep the mark array committed and perhaps fail with an OOM exception.
@PeterSolMS

Copy link
Copy Markdown
ContributorAuthor

With this change, we get much closer to actually exhausting the available memory in hard limit cases than before.

In a test case with hard limit set to 0x13c1d000 = 471,859,200, we only get to 331,468,800 committed bytes before running out of memory. The reason is that the memory set aside for bookkeeping is not sufficient, so we run into a situation where the mark array for a region can not be committed.

With this change, we get to 471,842,816 committed bytes before running out. "!dumpheap -stat" reports 462,803,767 bytes in objects, of which 10,684,992 are in free objects, so that we have a total of 452,118,775 bytes in useful objects. 6,078,464 are used for bookkeeping purposes (mainly for the mark array).

@frankbuckley

Copy link
Copy Markdown
Contributor

With this change, we get much closer to actually exhausting the available memory in hard limit cases than before.

In a test case with hard limit set to 0x13c1d000 = 471,859,200, we only get to 331,468,800 committed bytes before running out of memory...

With this change, we get to 471,842,816 committed bytes before running out...

Will this be backported to 7.0?

@ghostghost locked as resolved and limited conversation to collaborators Jan 12, 2023
@mangod9

Copy link
Copy Markdown
Member

/backport to release/7.0-staging

@github-actionsgithub-actionsBot unlocked this conversation Apr 24, 2023
@github-actions

Copy link
Copy Markdown
Contributor

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

@github-actions

Copy link
Copy Markdown
Contributor

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

$ git am --3way --ignore-whitespace --keep-non-patch changes.patch
Applying: As it turns out, it's not so easy to set aside a hard limit for the GC's bookkeeping, because some regions will be partially comitted and so will need more bookkeeping information as a percentage.
Using index info to reconstruct a base tree...
M	src/coreclr/gc/gc.cpp
M	src/coreclr/gc/gcpriv.h
Falling back to patching base and 3-way merge...
Auto-merging src/coreclr/gc/gcpriv.h
Auto-merging src/coreclr/gc/gc.cpp
CONFLICT (content): Merge conflict in src/coreclr/gc/gc.cpp
error: Failed to merge in the changes.
hint: Use 'git am --show-current-patch=diff' to see the failed patch
Patch failed at 0001 As it turns out, it's not so easy to set aside a hard limit for the GC's bookkeeping, because some regions will be partially comitted and so will need more bookkeeping information as a percentage.
When you have resolved this problem, run "git am --continue".
If you prefer to skip this patch, run "git am --skip" instead.
To restore the original branch and stop patching, run "git am --abort".
Error: The process '/usr/bin/git' failed with exit code 128

Please backport manually!

@github-actions

Copy link
Copy Markdown
Contributor

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

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

@github-actionsgithub-actionsBot locked as resolved and limited conversation to collaborators Apr 24, 2023
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.

Fail to get_free_region in thread_final_regions due to low memory for mark array might lead to AV.

5 participants

@PeterSolMS@Maoni0@frankbuckley@mangod9@cshung
, 'i'); if (__m === '*' || __re.test(location.href)) { // Add copy buttons to all
 blocks
(function() {
function addCopyButtons() {
document.querySelectorAll('pre code').forEach(function(codeBlock) {
if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;
codeBlock.parentElement.setAttribute('data-copy-added', 'true');
var btn = document.createElement('button');
btn.textContent = 'Copy';
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;';
btn.onmouseover = function() { this.style.opacity = '1'; };
btn.onmouseout = function() { this.style.opacity = '0.7'; };
btn.onclick = function() {
navigator.clipboard.writeText(codeBlock.textContent).then(function() {
btn.textContent = 'Copied!';
setTimeout(function() { btn.textContent = 'Copy'; }, 1500);
});
};
codeBlock.parentElement.style.position = 'relative';
codeBlock.parentElement.appendChild(btn);
});
}
addCopyButtons();
// Re-run on dynamic content
var observer = new MutationObserver(addCopyButtons);
observer.observe(document.body, { childList: true, subtree: true });
})();
}
} 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

Remove hard_limit_for_bookkeeping - #77480

Merged
PeterSolMS merged 5 commits into
dotnet:mainfrom
PeterSolMS:Remove_hard_limit_for_bookkeeping
Dec 12, 2022
Merged

Remove hard_limit_for_bookkeeping#77480
PeterSolMS merged 5 commits into
dotnet:mainfrom
PeterSolMS:Remove_hard_limit_for_bookkeeping

Conversation

@PeterSolMS

Copy link
Copy Markdown
Contributor

As it turns out, it's not so easy to set aside a hard limit for the GC's bookkeeping, because some regions will be partially comitted and so will need more bookkeeping information as a percentage.

So this removes the hard_limit_for_bookkeeping and associated fields, and instead commits memory for the mark array eagerly, even if BGC is not in progress.

…C's bookkeeping, because some regions will be partially comitted and so will need more bookkeeping information as a percentage.
So this removes the hard_limit_for_bookkeeping and associated fields, and instead commits memory for the mark array eagerly, even if BGC is not in progress.
@ghost

Copy link
Copy Markdown

Tagging subscribers to this area: @dotnet/gc
See info in area-owners.md if you want to be subscribed.

Issue Details

As it turns out, it's not so easy to set aside a hard limit for the GC's bookkeeping, because some regions will be partially comitted and so will need more bookkeeping information as a percentage.

So this removes the hard_limit_for_bookkeeping and associated fields, and instead commits memory for the mark array eagerly, even if BGC is not in progress.

Author:PeterSolMS
Assignees:PeterSolMS
Labels:

area-GC-coreclr

Milestone:-

@cshungcshung left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I liked this idea more than trying to set aside memory for bookkeeping. The one thing I am not sure about is that now we are committing the mark array for every region. If background GC is happening anyway, it might be fine because we will be committing them anyway, but what if we don't?

Comment threadsrc/coreclr/gc/gcpriv.h
Comment threadsrc/coreclr/gc/gc.cpp
dprintf (GC_TABLE_LOG, ("new seg %Ix, mark_array is %Ix",
heap_segment_mem (region), mark_array));
if (((region->flags & heap_segment_flags_ma_committed) == 0) &&
!commit_mark_array_new_seg (__this, region))

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Shall we guard this under gc_can_use_concurrent?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

commit_mark_array_new_seg shouldn't do anything if concurrent is disabled; although I'm looking at the code, we are not initializing background_saved_highest_address in init_gc_heap which we should. @PeterSolMS could you please add this (ie, init background_saved_highest_address and background_saved_lowest_address to 0 in init_gc_heap like we do with WKS GC)? we could still guard this with gc_can_use_concurrent just to indicate our intention but it's not essential.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

I just pushed changes with the initialization of background_saved_lowest_address and background_saved_highest_address, and the restoration of current_total_committed_bookkeeping.

@Maoni0

Copy link
Copy Markdown
Member

If background GC is happening anyway, it might be fine because we will be committing them anyway, but what if we don't?

that is the drawback with doing this. but if concurrent GC is enabled, it's very likely we'll need to do a BGC at some point so it's not too bad.

…ments back.
Initialize background_saved_lowest_address and background_saved_lowest_address.
Removed unrelated bug fix which is addressed by a separate PR.
@PeterSolMS

Copy link
Copy Markdown
ContributorAuthor

I think I found a hole in our logic - clear_region_info (called by return_free_region) will decommit the mark array in high memory load. When get_free_region tries to commit again, we'll fail and get the same AV as before. Perhaps this means we'll have to keep the mark array committed, i.e. disable the logic to decommit the mark array in high memory load?

…info.
The issue is that GC needs at least one free region, and it needs the mark array committed. So when it tries to get a region at the end, and we cannot commit the mark array, we cannot actually get a free region. Currently we AV in this case, but there really isn't a good option to recover at this point. So it's better to keep the mark array committed and perhaps fail with an OOM exception.
@PeterSolMS

Copy link
Copy Markdown
ContributorAuthor

With this change, we get much closer to actually exhausting the available memory in hard limit cases than before.

In a test case with hard limit set to 0x13c1d000 = 471,859,200, we only get to 331,468,800 committed bytes before running out of memory. The reason is that the memory set aside for bookkeeping is not sufficient, so we run into a situation where the mark array for a region can not be committed.

With this change, we get to 471,842,816 committed bytes before running out. "!dumpheap -stat" reports 462,803,767 bytes in objects, of which 10,684,992 are in free objects, so that we have a total of 452,118,775 bytes in useful objects. 6,078,464 are used for bookkeeping purposes (mainly for the mark array).

@frankbuckley

Copy link
Copy Markdown
Contributor

With this change, we get much closer to actually exhausting the available memory in hard limit cases than before.

In a test case with hard limit set to 0x13c1d000 = 471,859,200, we only get to 331,468,800 committed bytes before running out of memory...

With this change, we get to 471,842,816 committed bytes before running out...

Will this be backported to 7.0?

@ghostghost locked as resolved and limited conversation to collaborators Jan 12, 2023
@mangod9

Copy link
Copy Markdown
Member

/backport to release/7.0-staging

@github-actionsgithub-actionsBot unlocked this conversation Apr 24, 2023
@github-actions

Copy link
Copy Markdown
Contributor

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

@github-actions

Copy link
Copy Markdown
Contributor

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

$ git am --3way --ignore-whitespace --keep-non-patch changes.patch
Applying: As it turns out, it's not so easy to set aside a hard limit for the GC's bookkeeping, because some regions will be partially comitted and so will need more bookkeeping information as a percentage.
Using index info to reconstruct a base tree...
M	src/coreclr/gc/gc.cpp
M	src/coreclr/gc/gcpriv.h
Falling back to patching base and 3-way merge...
Auto-merging src/coreclr/gc/gcpriv.h
Auto-merging src/coreclr/gc/gc.cpp
CONFLICT (content): Merge conflict in src/coreclr/gc/gc.cpp
error: Failed to merge in the changes.
hint: Use 'git am --show-current-patch=diff' to see the failed patch
Patch failed at 0001 As it turns out, it's not so easy to set aside a hard limit for the GC's bookkeeping, because some regions will be partially comitted and so will need more bookkeeping information as a percentage.
When you have resolved this problem, run "git am --continue".
If you prefer to skip this patch, run "git am --skip" instead.
To restore the original branch and stop patching, run "git am --abort".
Error: The process '/usr/bin/git' failed with exit code 128

Please backport manually!

@github-actions

Copy link
Copy Markdown
Contributor

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

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

@github-actionsgithub-actionsBot locked as resolved and limited conversation to collaborators Apr 24, 2023
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.

Fail to get_free_region in thread_final_regions due to low memory for mark array might lead to AV.

5 participants

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

Remove hard_limit_for_bookkeeping - #77480

Merged
PeterSolMS merged 5 commits into
dotnet:mainfrom
PeterSolMS:Remove_hard_limit_for_bookkeeping
Dec 12, 2022
Merged

Remove hard_limit_for_bookkeeping#77480
PeterSolMS merged 5 commits into
dotnet:mainfrom
PeterSolMS:Remove_hard_limit_for_bookkeeping

Conversation

@PeterSolMS

Copy link
Copy Markdown
Contributor

As it turns out, it's not so easy to set aside a hard limit for the GC's bookkeeping, because some regions will be partially comitted and so will need more bookkeeping information as a percentage.

So this removes the hard_limit_for_bookkeeping and associated fields, and instead commits memory for the mark array eagerly, even if BGC is not in progress.

…C's bookkeeping, because some regions will be partially comitted and so will need more bookkeeping information as a percentage.
So this removes the hard_limit_for_bookkeeping and associated fields, and instead commits memory for the mark array eagerly, even if BGC is not in progress.
@ghost

Copy link
Copy Markdown

Tagging subscribers to this area: @dotnet/gc
See info in area-owners.md if you want to be subscribed.

Issue Details

As it turns out, it's not so easy to set aside a hard limit for the GC's bookkeeping, because some regions will be partially comitted and so will need more bookkeeping information as a percentage.

So this removes the hard_limit_for_bookkeeping and associated fields, and instead commits memory for the mark array eagerly, even if BGC is not in progress.

Author:PeterSolMS
Assignees:PeterSolMS
Labels:

area-GC-coreclr

Milestone:-

@cshungcshung left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I liked this idea more than trying to set aside memory for bookkeeping. The one thing I am not sure about is that now we are committing the mark array for every region. If background GC is happening anyway, it might be fine because we will be committing them anyway, but what if we don't?

Comment threadsrc/coreclr/gc/gcpriv.h
Comment threadsrc/coreclr/gc/gc.cpp
dprintf (GC_TABLE_LOG, ("new seg %Ix, mark_array is %Ix",
heap_segment_mem (region), mark_array));
if (((region->flags & heap_segment_flags_ma_committed) == 0) &&
!commit_mark_array_new_seg (__this, region))

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Shall we guard this under gc_can_use_concurrent?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

commit_mark_array_new_seg shouldn't do anything if concurrent is disabled; although I'm looking at the code, we are not initializing background_saved_highest_address in init_gc_heap which we should. @PeterSolMS could you please add this (ie, init background_saved_highest_address and background_saved_lowest_address to 0 in init_gc_heap like we do with WKS GC)? we could still guard this with gc_can_use_concurrent just to indicate our intention but it's not essential.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

I just pushed changes with the initialization of background_saved_lowest_address and background_saved_highest_address, and the restoration of current_total_committed_bookkeeping.

@Maoni0

Copy link
Copy Markdown
Member

If background GC is happening anyway, it might be fine because we will be committing them anyway, but what if we don't?

that is the drawback with doing this. but if concurrent GC is enabled, it's very likely we'll need to do a BGC at some point so it's not too bad.

…ments back.
Initialize background_saved_lowest_address and background_saved_lowest_address.
Removed unrelated bug fix which is addressed by a separate PR.
@PeterSolMS

Copy link
Copy Markdown
ContributorAuthor

I think I found a hole in our logic - clear_region_info (called by return_free_region) will decommit the mark array in high memory load. When get_free_region tries to commit again, we'll fail and get the same AV as before. Perhaps this means we'll have to keep the mark array committed, i.e. disable the logic to decommit the mark array in high memory load?

…info.
The issue is that GC needs at least one free region, and it needs the mark array committed. So when it tries to get a region at the end, and we cannot commit the mark array, we cannot actually get a free region. Currently we AV in this case, but there really isn't a good option to recover at this point. So it's better to keep the mark array committed and perhaps fail with an OOM exception.
@PeterSolMS

Copy link
Copy Markdown
ContributorAuthor

With this change, we get much closer to actually exhausting the available memory in hard limit cases than before.

In a test case with hard limit set to 0x13c1d000 = 471,859,200, we only get to 331,468,800 committed bytes before running out of memory. The reason is that the memory set aside for bookkeeping is not sufficient, so we run into a situation where the mark array for a region can not be committed.

With this change, we get to 471,842,816 committed bytes before running out. "!dumpheap -stat" reports 462,803,767 bytes in objects, of which 10,684,992 are in free objects, so that we have a total of 452,118,775 bytes in useful objects. 6,078,464 are used for bookkeeping purposes (mainly for the mark array).

@frankbuckley

Copy link
Copy Markdown
Contributor

With this change, we get much closer to actually exhausting the available memory in hard limit cases than before.

In a test case with hard limit set to 0x13c1d000 = 471,859,200, we only get to 331,468,800 committed bytes before running out of memory...

With this change, we get to 471,842,816 committed bytes before running out...

Will this be backported to 7.0?

@ghostghost locked as resolved and limited conversation to collaborators Jan 12, 2023
@mangod9

Copy link
Copy Markdown
Member

/backport to release/7.0-staging

@github-actionsgithub-actionsBot unlocked this conversation Apr 24, 2023
@github-actions

Copy link
Copy Markdown
Contributor

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

@github-actions

Copy link
Copy Markdown
Contributor

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

$ git am --3way --ignore-whitespace --keep-non-patch changes.patch
Applying: As it turns out, it's not so easy to set aside a hard limit for the GC's bookkeeping, because some regions will be partially comitted and so will need more bookkeeping information as a percentage.
Using index info to reconstruct a base tree...
M	src/coreclr/gc/gc.cpp
M	src/coreclr/gc/gcpriv.h
Falling back to patching base and 3-way merge...
Auto-merging src/coreclr/gc/gcpriv.h
Auto-merging src/coreclr/gc/gc.cpp
CONFLICT (content): Merge conflict in src/coreclr/gc/gc.cpp
error: Failed to merge in the changes.
hint: Use 'git am --show-current-patch=diff' to see the failed patch
Patch failed at 0001 As it turns out, it's not so easy to set aside a hard limit for the GC's bookkeeping, because some regions will be partially comitted and so will need more bookkeeping information as a percentage.
When you have resolved this problem, run "git am --continue".
If you prefer to skip this patch, run "git am --skip" instead.
To restore the original branch and stop patching, run "git am --abort".
Error: The process '/usr/bin/git' failed with exit code 128

Please backport manually!

@github-actions

Copy link
Copy Markdown
Contributor

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

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

@github-actionsgithub-actionsBot locked as resolved and limited conversation to collaborators Apr 24, 2023
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.

Fail to get_free_region in thread_final_regions due to low memory for mark array might lead to AV.

5 participants

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

Remove hard_limit_for_bookkeeping - #77480

Merged
PeterSolMS merged 5 commits into
dotnet:mainfrom
PeterSolMS:Remove_hard_limit_for_bookkeeping
Dec 12, 2022
Merged

Remove hard_limit_for_bookkeeping#77480
PeterSolMS merged 5 commits into
dotnet:mainfrom
PeterSolMS:Remove_hard_limit_for_bookkeeping

Conversation

@PeterSolMS

Copy link
Copy Markdown
Contributor

As it turns out, it's not so easy to set aside a hard limit for the GC's bookkeeping, because some regions will be partially comitted and so will need more bookkeeping information as a percentage.

So this removes the hard_limit_for_bookkeeping and associated fields, and instead commits memory for the mark array eagerly, even if BGC is not in progress.

…C's bookkeeping, because some regions will be partially comitted and so will need more bookkeeping information as a percentage.
So this removes the hard_limit_for_bookkeeping and associated fields, and instead commits memory for the mark array eagerly, even if BGC is not in progress.
@ghost

Copy link
Copy Markdown

Tagging subscribers to this area: @dotnet/gc
See info in area-owners.md if you want to be subscribed.

Issue Details

As it turns out, it's not so easy to set aside a hard limit for the GC's bookkeeping, because some regions will be partially comitted and so will need more bookkeeping information as a percentage.

So this removes the hard_limit_for_bookkeeping and associated fields, and instead commits memory for the mark array eagerly, even if BGC is not in progress.

Author:PeterSolMS
Assignees:PeterSolMS
Labels:

area-GC-coreclr

Milestone:-

@cshungcshung left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I liked this idea more than trying to set aside memory for bookkeeping. The one thing I am not sure about is that now we are committing the mark array for every region. If background GC is happening anyway, it might be fine because we will be committing them anyway, but what if we don't?

Comment threadsrc/coreclr/gc/gcpriv.h
Comment threadsrc/coreclr/gc/gc.cpp
dprintf (GC_TABLE_LOG, ("new seg %Ix, mark_array is %Ix",
heap_segment_mem (region), mark_array));
if (((region->flags & heap_segment_flags_ma_committed) == 0) &&
!commit_mark_array_new_seg (__this, region))

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Shall we guard this under gc_can_use_concurrent?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

commit_mark_array_new_seg shouldn't do anything if concurrent is disabled; although I'm looking at the code, we are not initializing background_saved_highest_address in init_gc_heap which we should. @PeterSolMS could you please add this (ie, init background_saved_highest_address and background_saved_lowest_address to 0 in init_gc_heap like we do with WKS GC)? we could still guard this with gc_can_use_concurrent just to indicate our intention but it's not essential.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

I just pushed changes with the initialization of background_saved_lowest_address and background_saved_highest_address, and the restoration of current_total_committed_bookkeeping.

@Maoni0

Copy link
Copy Markdown
Member

If background GC is happening anyway, it might be fine because we will be committing them anyway, but what if we don't?

that is the drawback with doing this. but if concurrent GC is enabled, it's very likely we'll need to do a BGC at some point so it's not too bad.

…ments back.
Initialize background_saved_lowest_address and background_saved_lowest_address.
Removed unrelated bug fix which is addressed by a separate PR.
@PeterSolMS

Copy link
Copy Markdown
ContributorAuthor

I think I found a hole in our logic - clear_region_info (called by return_free_region) will decommit the mark array in high memory load. When get_free_region tries to commit again, we'll fail and get the same AV as before. Perhaps this means we'll have to keep the mark array committed, i.e. disable the logic to decommit the mark array in high memory load?

…info.
The issue is that GC needs at least one free region, and it needs the mark array committed. So when it tries to get a region at the end, and we cannot commit the mark array, we cannot actually get a free region. Currently we AV in this case, but there really isn't a good option to recover at this point. So it's better to keep the mark array committed and perhaps fail with an OOM exception.
@PeterSolMS

Copy link
Copy Markdown
ContributorAuthor

With this change, we get much closer to actually exhausting the available memory in hard limit cases than before.

In a test case with hard limit set to 0x13c1d000 = 471,859,200, we only get to 331,468,800 committed bytes before running out of memory. The reason is that the memory set aside for bookkeeping is not sufficient, so we run into a situation where the mark array for a region can not be committed.

With this change, we get to 471,842,816 committed bytes before running out. "!dumpheap -stat" reports 462,803,767 bytes in objects, of which 10,684,992 are in free objects, so that we have a total of 452,118,775 bytes in useful objects. 6,078,464 are used for bookkeeping purposes (mainly for the mark array).

@frankbuckley

Copy link
Copy Markdown
Contributor

With this change, we get much closer to actually exhausting the available memory in hard limit cases than before.

In a test case with hard limit set to 0x13c1d000 = 471,859,200, we only get to 331,468,800 committed bytes before running out of memory...

With this change, we get to 471,842,816 committed bytes before running out...

Will this be backported to 7.0?

@ghostghost locked as resolved and limited conversation to collaborators Jan 12, 2023
@mangod9

Copy link
Copy Markdown
Member

/backport to release/7.0-staging

@github-actionsgithub-actionsBot unlocked this conversation Apr 24, 2023
@github-actions

Copy link
Copy Markdown
Contributor

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

@github-actions

Copy link
Copy Markdown
Contributor

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

$ git am --3way --ignore-whitespace --keep-non-patch changes.patch
Applying: As it turns out, it's not so easy to set aside a hard limit for the GC's bookkeeping, because some regions will be partially comitted and so will need more bookkeeping information as a percentage.
Using index info to reconstruct a base tree...
M	src/coreclr/gc/gc.cpp
M	src/coreclr/gc/gcpriv.h
Falling back to patching base and 3-way merge...
Auto-merging src/coreclr/gc/gcpriv.h
Auto-merging src/coreclr/gc/gc.cpp
CONFLICT (content): Merge conflict in src/coreclr/gc/gc.cpp
error: Failed to merge in the changes.
hint: Use 'git am --show-current-patch=diff' to see the failed patch
Patch failed at 0001 As it turns out, it's not so easy to set aside a hard limit for the GC's bookkeeping, because some regions will be partially comitted and so will need more bookkeeping information as a percentage.
When you have resolved this problem, run "git am --continue".
If you prefer to skip this patch, run "git am --skip" instead.
To restore the original branch and stop patching, run "git am --abort".
Error: The process '/usr/bin/git' failed with exit code 128

Please backport manually!

@github-actions

Copy link
Copy Markdown
Contributor

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

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

@github-actionsgithub-actionsBot locked as resolved and limited conversation to collaborators Apr 24, 2023
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.

Fail to get_free_region in thread_final_regions due to low memory for mark array might lead to AV.

5 participants

@PeterSolMS@Maoni0@frankbuckley@mangod9@cshung
, 'i'); if (__m === '*' || __re.test(location.href)) { // Strip utm_, fbclid, gclid, etc. from all links on page (function() { var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content', 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid', 'ref', 'ref_src', 'source', 'medium', 'campaign']; function cleanUrl(url) { try { var u = new URL(url, window.location.origin); var changed = false; trackingParams.forEach(function(p) { if (u.searchParams.has(p)) { u.searchParams.delete(p); changed = true; } }); return changed ? u.toString() : url; } catch (e) { return url; } } function cleanLinks() { document.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } cleanLinks(); var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1) { if (node.tagName === 'A') cleanLinks(); node.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } 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

Remove hard_limit_for_bookkeeping - #77480

Merged
PeterSolMS merged 5 commits into
dotnet:mainfrom
PeterSolMS:Remove_hard_limit_for_bookkeeping
Dec 12, 2022
Merged

Remove hard_limit_for_bookkeeping#77480
PeterSolMS merged 5 commits into
dotnet:mainfrom
PeterSolMS:Remove_hard_limit_for_bookkeeping

Conversation

@PeterSolMS

Copy link
Copy Markdown
Contributor

As it turns out, it's not so easy to set aside a hard limit for the GC's bookkeeping, because some regions will be partially comitted and so will need more bookkeeping information as a percentage.

So this removes the hard_limit_for_bookkeeping and associated fields, and instead commits memory for the mark array eagerly, even if BGC is not in progress.

…C's bookkeeping, because some regions will be partially comitted and so will need more bookkeeping information as a percentage.
So this removes the hard_limit_for_bookkeeping and associated fields, and instead commits memory for the mark array eagerly, even if BGC is not in progress.
@ghost

Copy link
Copy Markdown

Tagging subscribers to this area: @dotnet/gc
See info in area-owners.md if you want to be subscribed.

Issue Details

As it turns out, it's not so easy to set aside a hard limit for the GC's bookkeeping, because some regions will be partially comitted and so will need more bookkeeping information as a percentage.

So this removes the hard_limit_for_bookkeeping and associated fields, and instead commits memory for the mark array eagerly, even if BGC is not in progress.

Author:PeterSolMS
Assignees:PeterSolMS
Labels:

area-GC-coreclr

Milestone:-

@cshungcshung left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I liked this idea more than trying to set aside memory for bookkeeping. The one thing I am not sure about is that now we are committing the mark array for every region. If background GC is happening anyway, it might be fine because we will be committing them anyway, but what if we don't?

Comment threadsrc/coreclr/gc/gcpriv.h
Comment threadsrc/coreclr/gc/gc.cpp
dprintf (GC_TABLE_LOG, ("new seg %Ix, mark_array is %Ix",
heap_segment_mem (region), mark_array));
if (((region->flags & heap_segment_flags_ma_committed) == 0) &&
!commit_mark_array_new_seg (__this, region))

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Shall we guard this under gc_can_use_concurrent?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

commit_mark_array_new_seg shouldn't do anything if concurrent is disabled; although I'm looking at the code, we are not initializing background_saved_highest_address in init_gc_heap which we should. @PeterSolMS could you please add this (ie, init background_saved_highest_address and background_saved_lowest_address to 0 in init_gc_heap like we do with WKS GC)? we could still guard this with gc_can_use_concurrent just to indicate our intention but it's not essential.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

I just pushed changes with the initialization of background_saved_lowest_address and background_saved_highest_address, and the restoration of current_total_committed_bookkeeping.

@Maoni0

Copy link
Copy Markdown
Member

If background GC is happening anyway, it might be fine because we will be committing them anyway, but what if we don't?

that is the drawback with doing this. but if concurrent GC is enabled, it's very likely we'll need to do a BGC at some point so it's not too bad.

…ments back.
Initialize background_saved_lowest_address and background_saved_lowest_address.
Removed unrelated bug fix which is addressed by a separate PR.
@PeterSolMS

Copy link
Copy Markdown
ContributorAuthor

I think I found a hole in our logic - clear_region_info (called by return_free_region) will decommit the mark array in high memory load. When get_free_region tries to commit again, we'll fail and get the same AV as before. Perhaps this means we'll have to keep the mark array committed, i.e. disable the logic to decommit the mark array in high memory load?

…info.
The issue is that GC needs at least one free region, and it needs the mark array committed. So when it tries to get a region at the end, and we cannot commit the mark array, we cannot actually get a free region. Currently we AV in this case, but there really isn't a good option to recover at this point. So it's better to keep the mark array committed and perhaps fail with an OOM exception.
@PeterSolMS

Copy link
Copy Markdown
ContributorAuthor

With this change, we get much closer to actually exhausting the available memory in hard limit cases than before.

In a test case with hard limit set to 0x13c1d000 = 471,859,200, we only get to 331,468,800 committed bytes before running out of memory. The reason is that the memory set aside for bookkeeping is not sufficient, so we run into a situation where the mark array for a region can not be committed.

With this change, we get to 471,842,816 committed bytes before running out. "!dumpheap -stat" reports 462,803,767 bytes in objects, of which 10,684,992 are in free objects, so that we have a total of 452,118,775 bytes in useful objects. 6,078,464 are used for bookkeeping purposes (mainly for the mark array).

@frankbuckley

Copy link
Copy Markdown
Contributor

With this change, we get much closer to actually exhausting the available memory in hard limit cases than before.

In a test case with hard limit set to 0x13c1d000 = 471,859,200, we only get to 331,468,800 committed bytes before running out of memory...

With this change, we get to 471,842,816 committed bytes before running out...

Will this be backported to 7.0?

@ghostghost locked as resolved and limited conversation to collaborators Jan 12, 2023
@mangod9

Copy link
Copy Markdown
Member

/backport to release/7.0-staging

@github-actionsgithub-actionsBot unlocked this conversation Apr 24, 2023
@github-actions

Copy link
Copy Markdown
Contributor

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

@github-actions

Copy link
Copy Markdown
Contributor

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

$ git am --3way --ignore-whitespace --keep-non-patch changes.patch
Applying: As it turns out, it's not so easy to set aside a hard limit for the GC's bookkeeping, because some regions will be partially comitted and so will need more bookkeeping information as a percentage.
Using index info to reconstruct a base tree...
M	src/coreclr/gc/gc.cpp
M	src/coreclr/gc/gcpriv.h
Falling back to patching base and 3-way merge...
Auto-merging src/coreclr/gc/gcpriv.h
Auto-merging src/coreclr/gc/gc.cpp
CONFLICT (content): Merge conflict in src/coreclr/gc/gc.cpp
error: Failed to merge in the changes.
hint: Use 'git am --show-current-patch=diff' to see the failed patch
Patch failed at 0001 As it turns out, it's not so easy to set aside a hard limit for the GC's bookkeeping, because some regions will be partially comitted and so will need more bookkeeping information as a percentage.
When you have resolved this problem, run "git am --continue".
If you prefer to skip this patch, run "git am --skip" instead.
To restore the original branch and stop patching, run "git am --abort".
Error: The process '/usr/bin/git' failed with exit code 128

Please backport manually!

@github-actions

Copy link
Copy Markdown
Contributor

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

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

@github-actionsgithub-actionsBot locked as resolved and limited conversation to collaborators Apr 24, 2023
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.

Fail to get_free_region in thread_final_regions due to low memory for mark array might lead to AV.

5 participants

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

Remove hard_limit_for_bookkeeping - #77480

Merged
PeterSolMS merged 5 commits into
dotnet:mainfrom
PeterSolMS:Remove_hard_limit_for_bookkeeping
Dec 12, 2022
Merged

Remove hard_limit_for_bookkeeping#77480
PeterSolMS merged 5 commits into
dotnet:mainfrom
PeterSolMS:Remove_hard_limit_for_bookkeeping

Conversation

@PeterSolMS

Copy link
Copy Markdown
Contributor

As it turns out, it's not so easy to set aside a hard limit for the GC's bookkeeping, because some regions will be partially comitted and so will need more bookkeeping information as a percentage.

So this removes the hard_limit_for_bookkeeping and associated fields, and instead commits memory for the mark array eagerly, even if BGC is not in progress.

…C's bookkeeping, because some regions will be partially comitted and so will need more bookkeeping information as a percentage.
So this removes the hard_limit_for_bookkeeping and associated fields, and instead commits memory for the mark array eagerly, even if BGC is not in progress.
@ghost

Copy link
Copy Markdown

Tagging subscribers to this area: @dotnet/gc
See info in area-owners.md if you want to be subscribed.

Issue Details

As it turns out, it's not so easy to set aside a hard limit for the GC's bookkeeping, because some regions will be partially comitted and so will need more bookkeeping information as a percentage.

So this removes the hard_limit_for_bookkeeping and associated fields, and instead commits memory for the mark array eagerly, even if BGC is not in progress.

Author:PeterSolMS
Assignees:PeterSolMS
Labels:

area-GC-coreclr

Milestone:-

@cshungcshung left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I liked this idea more than trying to set aside memory for bookkeeping. The one thing I am not sure about is that now we are committing the mark array for every region. If background GC is happening anyway, it might be fine because we will be committing them anyway, but what if we don't?

Comment threadsrc/coreclr/gc/gcpriv.h
Comment threadsrc/coreclr/gc/gc.cpp
dprintf (GC_TABLE_LOG, ("new seg %Ix, mark_array is %Ix",
heap_segment_mem (region), mark_array));
if (((region->flags & heap_segment_flags_ma_committed) == 0) &&
!commit_mark_array_new_seg (__this, region))

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Shall we guard this under gc_can_use_concurrent?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

commit_mark_array_new_seg shouldn't do anything if concurrent is disabled; although I'm looking at the code, we are not initializing background_saved_highest_address in init_gc_heap which we should. @PeterSolMS could you please add this (ie, init background_saved_highest_address and background_saved_lowest_address to 0 in init_gc_heap like we do with WKS GC)? we could still guard this with gc_can_use_concurrent just to indicate our intention but it's not essential.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

I just pushed changes with the initialization of background_saved_lowest_address and background_saved_highest_address, and the restoration of current_total_committed_bookkeeping.

@Maoni0

Copy link
Copy Markdown
Member

If background GC is happening anyway, it might be fine because we will be committing them anyway, but what if we don't?

that is the drawback with doing this. but if concurrent GC is enabled, it's very likely we'll need to do a BGC at some point so it's not too bad.

…ments back.
Initialize background_saved_lowest_address and background_saved_lowest_address.
Removed unrelated bug fix which is addressed by a separate PR.
@PeterSolMS

Copy link
Copy Markdown
ContributorAuthor

I think I found a hole in our logic - clear_region_info (called by return_free_region) will decommit the mark array in high memory load. When get_free_region tries to commit again, we'll fail and get the same AV as before. Perhaps this means we'll have to keep the mark array committed, i.e. disable the logic to decommit the mark array in high memory load?

…info.
The issue is that GC needs at least one free region, and it needs the mark array committed. So when it tries to get a region at the end, and we cannot commit the mark array, we cannot actually get a free region. Currently we AV in this case, but there really isn't a good option to recover at this point. So it's better to keep the mark array committed and perhaps fail with an OOM exception.
@PeterSolMS

Copy link
Copy Markdown
ContributorAuthor

With this change, we get much closer to actually exhausting the available memory in hard limit cases than before.

In a test case with hard limit set to 0x13c1d000 = 471,859,200, we only get to 331,468,800 committed bytes before running out of memory. The reason is that the memory set aside for bookkeeping is not sufficient, so we run into a situation where the mark array for a region can not be committed.

With this change, we get to 471,842,816 committed bytes before running out. "!dumpheap -stat" reports 462,803,767 bytes in objects, of which 10,684,992 are in free objects, so that we have a total of 452,118,775 bytes in useful objects. 6,078,464 are used for bookkeeping purposes (mainly for the mark array).

@frankbuckley

Copy link
Copy Markdown
Contributor

With this change, we get much closer to actually exhausting the available memory in hard limit cases than before.

In a test case with hard limit set to 0x13c1d000 = 471,859,200, we only get to 331,468,800 committed bytes before running out of memory...

With this change, we get to 471,842,816 committed bytes before running out...

Will this be backported to 7.0?

@ghostghost locked as resolved and limited conversation to collaborators Jan 12, 2023
@mangod9

Copy link
Copy Markdown
Member

/backport to release/7.0-staging

@github-actionsgithub-actionsBot unlocked this conversation Apr 24, 2023
@github-actions

Copy link
Copy Markdown
Contributor

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

@github-actions

Copy link
Copy Markdown
Contributor

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

$ git am --3way --ignore-whitespace --keep-non-patch changes.patch
Applying: As it turns out, it's not so easy to set aside a hard limit for the GC's bookkeeping, because some regions will be partially comitted and so will need more bookkeeping information as a percentage.
Using index info to reconstruct a base tree...
M	src/coreclr/gc/gc.cpp
M	src/coreclr/gc/gcpriv.h
Falling back to patching base and 3-way merge...
Auto-merging src/coreclr/gc/gcpriv.h
Auto-merging src/coreclr/gc/gc.cpp
CONFLICT (content): Merge conflict in src/coreclr/gc/gc.cpp
error: Failed to merge in the changes.
hint: Use 'git am --show-current-patch=diff' to see the failed patch
Patch failed at 0001 As it turns out, it's not so easy to set aside a hard limit for the GC's bookkeeping, because some regions will be partially comitted and so will need more bookkeeping information as a percentage.
When you have resolved this problem, run "git am --continue".
If you prefer to skip this patch, run "git am --skip" instead.
To restore the original branch and stop patching, run "git am --abort".
Error: The process '/usr/bin/git' failed with exit code 128

Please backport manually!

@github-actions

Copy link
Copy Markdown
Contributor

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

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

@github-actionsgithub-actionsBot locked as resolved and limited conversation to collaborators Apr 24, 2023
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.

Fail to get_free_region in thread_final_regions due to low memory for mark array might lead to AV.

5 participants

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

Remove hard_limit_for_bookkeeping - #77480

Merged
PeterSolMS merged 5 commits into
dotnet:mainfrom
PeterSolMS:Remove_hard_limit_for_bookkeeping
Dec 12, 2022
Merged

Remove hard_limit_for_bookkeeping#77480
PeterSolMS merged 5 commits into
dotnet:mainfrom
PeterSolMS:Remove_hard_limit_for_bookkeeping

Conversation

@PeterSolMS

Copy link
Copy Markdown
Contributor

As it turns out, it's not so easy to set aside a hard limit for the GC's bookkeeping, because some regions will be partially comitted and so will need more bookkeeping information as a percentage.

So this removes the hard_limit_for_bookkeeping and associated fields, and instead commits memory for the mark array eagerly, even if BGC is not in progress.

…C's bookkeeping, because some regions will be partially comitted and so will need more bookkeeping information as a percentage.
So this removes the hard_limit_for_bookkeeping and associated fields, and instead commits memory for the mark array eagerly, even if BGC is not in progress.
@ghost

Copy link
Copy Markdown

Tagging subscribers to this area: @dotnet/gc
See info in area-owners.md if you want to be subscribed.

Issue Details

As it turns out, it's not so easy to set aside a hard limit for the GC's bookkeeping, because some regions will be partially comitted and so will need more bookkeeping information as a percentage.

So this removes the hard_limit_for_bookkeeping and associated fields, and instead commits memory for the mark array eagerly, even if BGC is not in progress.

Author:PeterSolMS
Assignees:PeterSolMS
Labels:

area-GC-coreclr

Milestone:-

@cshungcshung left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I liked this idea more than trying to set aside memory for bookkeeping. The one thing I am not sure about is that now we are committing the mark array for every region. If background GC is happening anyway, it might be fine because we will be committing them anyway, but what if we don't?

Comment threadsrc/coreclr/gc/gcpriv.h
Comment threadsrc/coreclr/gc/gc.cpp
dprintf (GC_TABLE_LOG, ("new seg %Ix, mark_array is %Ix",
heap_segment_mem (region), mark_array));
if (((region->flags & heap_segment_flags_ma_committed) == 0) &&
!commit_mark_array_new_seg (__this, region))

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Shall we guard this under gc_can_use_concurrent?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

commit_mark_array_new_seg shouldn't do anything if concurrent is disabled; although I'm looking at the code, we are not initializing background_saved_highest_address in init_gc_heap which we should. @PeterSolMS could you please add this (ie, init background_saved_highest_address and background_saved_lowest_address to 0 in init_gc_heap like we do with WKS GC)? we could still guard this with gc_can_use_concurrent just to indicate our intention but it's not essential.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

I just pushed changes with the initialization of background_saved_lowest_address and background_saved_highest_address, and the restoration of current_total_committed_bookkeeping.

@Maoni0

Copy link
Copy Markdown
Member

If background GC is happening anyway, it might be fine because we will be committing them anyway, but what if we don't?

that is the drawback with doing this. but if concurrent GC is enabled, it's very likely we'll need to do a BGC at some point so it's not too bad.

…ments back.
Initialize background_saved_lowest_address and background_saved_lowest_address.
Removed unrelated bug fix which is addressed by a separate PR.
@PeterSolMS

Copy link
Copy Markdown
ContributorAuthor

I think I found a hole in our logic - clear_region_info (called by return_free_region) will decommit the mark array in high memory load. When get_free_region tries to commit again, we'll fail and get the same AV as before. Perhaps this means we'll have to keep the mark array committed, i.e. disable the logic to decommit the mark array in high memory load?

…info.
The issue is that GC needs at least one free region, and it needs the mark array committed. So when it tries to get a region at the end, and we cannot commit the mark array, we cannot actually get a free region. Currently we AV in this case, but there really isn't a good option to recover at this point. So it's better to keep the mark array committed and perhaps fail with an OOM exception.
@PeterSolMS

Copy link
Copy Markdown
ContributorAuthor

With this change, we get much closer to actually exhausting the available memory in hard limit cases than before.

In a test case with hard limit set to 0x13c1d000 = 471,859,200, we only get to 331,468,800 committed bytes before running out of memory. The reason is that the memory set aside for bookkeeping is not sufficient, so we run into a situation where the mark array for a region can not be committed.

With this change, we get to 471,842,816 committed bytes before running out. "!dumpheap -stat" reports 462,803,767 bytes in objects, of which 10,684,992 are in free objects, so that we have a total of 452,118,775 bytes in useful objects. 6,078,464 are used for bookkeeping purposes (mainly for the mark array).

@frankbuckley

Copy link
Copy Markdown
Contributor

With this change, we get much closer to actually exhausting the available memory in hard limit cases than before.

In a test case with hard limit set to 0x13c1d000 = 471,859,200, we only get to 331,468,800 committed bytes before running out of memory...

With this change, we get to 471,842,816 committed bytes before running out...

Will this be backported to 7.0?

@ghostghost locked as resolved and limited conversation to collaborators Jan 12, 2023
@mangod9

Copy link
Copy Markdown
Member

/backport to release/7.0-staging

@github-actionsgithub-actionsBot unlocked this conversation Apr 24, 2023
@github-actions

Copy link
Copy Markdown
Contributor

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

@github-actions

Copy link
Copy Markdown
Contributor

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

$ git am --3way --ignore-whitespace --keep-non-patch changes.patch
Applying: As it turns out, it's not so easy to set aside a hard limit for the GC's bookkeeping, because some regions will be partially comitted and so will need more bookkeeping information as a percentage.
Using index info to reconstruct a base tree...
M	src/coreclr/gc/gc.cpp
M	src/coreclr/gc/gcpriv.h
Falling back to patching base and 3-way merge...
Auto-merging src/coreclr/gc/gcpriv.h
Auto-merging src/coreclr/gc/gc.cpp
CONFLICT (content): Merge conflict in src/coreclr/gc/gc.cpp
error: Failed to merge in the changes.
hint: Use 'git am --show-current-patch=diff' to see the failed patch
Patch failed at 0001 As it turns out, it's not so easy to set aside a hard limit for the GC's bookkeeping, because some regions will be partially comitted and so will need more bookkeeping information as a percentage.
When you have resolved this problem, run "git am --continue".
If you prefer to skip this patch, run "git am --skip" instead.
To restore the original branch and stop patching, run "git am --abort".
Error: The process '/usr/bin/git' failed with exit code 128

Please backport manually!

@github-actions

Copy link
Copy Markdown
Contributor

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

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

@github-actionsgithub-actionsBot locked as resolved and limited conversation to collaborators Apr 24, 2023
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.

Fail to get_free_region in thread_final_regions due to low memory for mark array might lead to AV.

5 participants

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

Remove hard_limit_for_bookkeeping - #77480

Merged
PeterSolMS merged 5 commits into
dotnet:mainfrom
PeterSolMS:Remove_hard_limit_for_bookkeeping
Dec 12, 2022
Merged

Remove hard_limit_for_bookkeeping#77480
PeterSolMS merged 5 commits into
dotnet:mainfrom
PeterSolMS:Remove_hard_limit_for_bookkeeping

Conversation

@PeterSolMS

Copy link
Copy Markdown
Contributor

As it turns out, it's not so easy to set aside a hard limit for the GC's bookkeeping, because some regions will be partially comitted and so will need more bookkeeping information as a percentage.

So this removes the hard_limit_for_bookkeeping and associated fields, and instead commits memory for the mark array eagerly, even if BGC is not in progress.

…C's bookkeeping, because some regions will be partially comitted and so will need more bookkeeping information as a percentage.
So this removes the hard_limit_for_bookkeeping and associated fields, and instead commits memory for the mark array eagerly, even if BGC is not in progress.
@ghost

Copy link
Copy Markdown

Tagging subscribers to this area: @dotnet/gc
See info in area-owners.md if you want to be subscribed.

Issue Details

As it turns out, it's not so easy to set aside a hard limit for the GC's bookkeeping, because some regions will be partially comitted and so will need more bookkeeping information as a percentage.

So this removes the hard_limit_for_bookkeeping and associated fields, and instead commits memory for the mark array eagerly, even if BGC is not in progress.

Author:PeterSolMS
Assignees:PeterSolMS
Labels:

area-GC-coreclr

Milestone:-

@cshungcshung left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I liked this idea more than trying to set aside memory for bookkeeping. The one thing I am not sure about is that now we are committing the mark array for every region. If background GC is happening anyway, it might be fine because we will be committing them anyway, but what if we don't?

Comment threadsrc/coreclr/gc/gcpriv.h
Comment threadsrc/coreclr/gc/gc.cpp
dprintf (GC_TABLE_LOG, ("new seg %Ix, mark_array is %Ix",
heap_segment_mem (region), mark_array));
if (((region->flags & heap_segment_flags_ma_committed) == 0) &&
!commit_mark_array_new_seg (__this, region))

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Shall we guard this under gc_can_use_concurrent?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

commit_mark_array_new_seg shouldn't do anything if concurrent is disabled; although I'm looking at the code, we are not initializing background_saved_highest_address in init_gc_heap which we should. @PeterSolMS could you please add this (ie, init background_saved_highest_address and background_saved_lowest_address to 0 in init_gc_heap like we do with WKS GC)? we could still guard this with gc_can_use_concurrent just to indicate our intention but it's not essential.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

I just pushed changes with the initialization of background_saved_lowest_address and background_saved_highest_address, and the restoration of current_total_committed_bookkeeping.

@Maoni0

Copy link
Copy Markdown
Member

If background GC is happening anyway, it might be fine because we will be committing them anyway, but what if we don't?

that is the drawback with doing this. but if concurrent GC is enabled, it's very likely we'll need to do a BGC at some point so it's not too bad.

…ments back.
Initialize background_saved_lowest_address and background_saved_lowest_address.
Removed unrelated bug fix which is addressed by a separate PR.
@PeterSolMS

Copy link
Copy Markdown
ContributorAuthor

I think I found a hole in our logic - clear_region_info (called by return_free_region) will decommit the mark array in high memory load. When get_free_region tries to commit again, we'll fail and get the same AV as before. Perhaps this means we'll have to keep the mark array committed, i.e. disable the logic to decommit the mark array in high memory load?

…info.
The issue is that GC needs at least one free region, and it needs the mark array committed. So when it tries to get a region at the end, and we cannot commit the mark array, we cannot actually get a free region. Currently we AV in this case, but there really isn't a good option to recover at this point. So it's better to keep the mark array committed and perhaps fail with an OOM exception.
@PeterSolMS

Copy link
Copy Markdown
ContributorAuthor

With this change, we get much closer to actually exhausting the available memory in hard limit cases than before.

In a test case with hard limit set to 0x13c1d000 = 471,859,200, we only get to 331,468,800 committed bytes before running out of memory. The reason is that the memory set aside for bookkeeping is not sufficient, so we run into a situation where the mark array for a region can not be committed.

With this change, we get to 471,842,816 committed bytes before running out. "!dumpheap -stat" reports 462,803,767 bytes in objects, of which 10,684,992 are in free objects, so that we have a total of 452,118,775 bytes in useful objects. 6,078,464 are used for bookkeeping purposes (mainly for the mark array).

@frankbuckley

Copy link
Copy Markdown
Contributor

With this change, we get much closer to actually exhausting the available memory in hard limit cases than before.

In a test case with hard limit set to 0x13c1d000 = 471,859,200, we only get to 331,468,800 committed bytes before running out of memory...

With this change, we get to 471,842,816 committed bytes before running out...

Will this be backported to 7.0?

@ghostghost locked as resolved and limited conversation to collaborators Jan 12, 2023
@mangod9

Copy link
Copy Markdown
Member

/backport to release/7.0-staging

@github-actionsgithub-actionsBot unlocked this conversation Apr 24, 2023
@github-actions

Copy link
Copy Markdown
Contributor

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

@github-actions

Copy link
Copy Markdown
Contributor

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

$ git am --3way --ignore-whitespace --keep-non-patch changes.patch
Applying: As it turns out, it's not so easy to set aside a hard limit for the GC's bookkeeping, because some regions will be partially comitted and so will need more bookkeeping information as a percentage.
Using index info to reconstruct a base tree...
M	src/coreclr/gc/gc.cpp
M	src/coreclr/gc/gcpriv.h
Falling back to patching base and 3-way merge...
Auto-merging src/coreclr/gc/gcpriv.h
Auto-merging src/coreclr/gc/gc.cpp
CONFLICT (content): Merge conflict in src/coreclr/gc/gc.cpp
error: Failed to merge in the changes.
hint: Use 'git am --show-current-patch=diff' to see the failed patch
Patch failed at 0001 As it turns out, it's not so easy to set aside a hard limit for the GC's bookkeeping, because some regions will be partially comitted and so will need more bookkeeping information as a percentage.
When you have resolved this problem, run "git am --continue".
If you prefer to skip this patch, run "git am --skip" instead.
To restore the original branch and stop patching, run "git am --abort".
Error: The process '/usr/bin/git' failed with exit code 128

Please backport manually!

@github-actions

Copy link
Copy Markdown
Contributor

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

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

@github-actionsgithub-actionsBot locked as resolved and limited conversation to collaborators Apr 24, 2023
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.

Fail to get_free_region in thread_final_regions due to low memory for mark array might lead to AV.

5 participants

@PeterSolMS@Maoni0@frankbuckley@mangod9@cshung