Skip to content
This repository was archived by the owner on Jan 23, 2023. It is now read-only.

Bgc suspension fixes #27729

Merged
merged 11 commits into from
Nov 13, 2019
Merged

Bgc suspension fixes #27729

merged 11 commits into from
Nov 13, 2019

Conversation

PeterSolMS
Copy link

Two fixes to speed up suspension for foreground GCs while background GC is in progress:

  • In background_mark_simple1, check g_fSuspensionPending and if it is set, save the state of the work and restart the loop - this will call allow_fgc() and thus allow a foreground GC to take place. Some measurements indicated this would regress performance of background_mark_simple1, but the effect seems to have disappeared when I remeasured. Nonetheless I'm curious if there is a better way.

  • In revisit_written_page, call allow_fgc() at the end - this allow a foreground GC to happen whenever we are done with revisiting a written page. This change was suggested by Maoni.

…d_first_object when finding the start of objects for marking interior pointers.
…t in find_first_object when finding the start of objects for marking interior pointers."

This reverts commit 9d53ff9.
…GC is in progress:

- In background_mark_simple1, check g_fSuspensionPending and if it is set, save the state of the work and restart the loop - this will call allow_fgc() and thus allow a foreground GC to take place.

- In revisit_written_page, call allow_fgc() at the end - this allow a foreground GC to happen whenever we are done with revisiting a written page.
@Maoni0
Copy link
Member

Maoni0 commented Nov 7, 2019

instead of checking something like g_fSuspensionPending, it might be better to count the already marked refs like we do with the ones we need to mark; since we do less work with marked refs we can exit the loop say 16 * num_partial_refs. this way we don't need to bring in the g_fSuspensionPending var at all (which would be more elegant 'cause it's supposed to be encapsulate in the allow_fgc logic). something like this:

                    int num_unmarked_refs = num_partial_refs;
                    int num_marked_refs = num_unmarked_refs * 16;

                    go_through_object (method_table(oo), oo, s, ppslot,
                                       start, use_start, (oo + s),
                    {
                        uint8_t* o = *ppslot;
                        Prefetch(o);

                        if (background_mark (o,
                                            background_saved_lowest_address,
                                            background_saved_highest_address))
                        {
                            // same code here
                        }
                        else if (--num_marked_refs == 0)
                        {
                            *place = (uint8_t*)(ppslot + 1);
                            goto more_to_do;
                        }

                    }
                    );

what do you think?

@PeterSolMS
Copy link
Author

I considered this but worried that the additional variable would live on the stack and thus we'd have additional memory references. I'll give it a try...

@PeterSolMS
Copy link
Author

Ok, I tried your counter solution and found that the additional counter lives in a register, not on the stack (in x64 release). Also, in PerfView I could not see a speed difference between the two.

I made the following small tweaks to your suggested solution:

  • I believe "else if (--num_marked_refs == 0)" is incorrect because it doesn't address the case where the child objects were unmarked, but didn't have pointers themselves.
  • I changed the variable names to "num_pushed_refs" and "num_processed_refs" because it seemed more accurate.

Copy link
Member

@Maoni0 Maoni0 left a comment

Choose a reason for hiding this comment

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

LGTM!

@sergiy-k sergiy-k merged commit a7678f5 into dotnet:master Nov 13, 2019
MichalStrehovsky pushed a commit to MichalStrehovsky/corert that referenced this pull request Mar 28, 2020
* Changes to set gen0 bricks always. This reduces the time spent in find_first_object when finding the start of objects for marking interior pointers.

* Revert "Changes to set gen0 bricks always. This reduces the time spent in find_first_object when finding the start of objects for marking interior pointers."

This reverts commit dotnet/coreclr@9d53ff9.

* Two fixes to speed up suspension for foreground GCs while background GC is in progress:

- In background_mark_simple1, check g_fSuspensionPending and if it is set, save the state of the work and restart the loop - this will call allow_fgc() and thus allow a foreground GC to take place.

- In revisit_written_page, call allow_fgc() at the end - this allow a foreground GC to happen whenever we are done with revisiting a written page.

* Addressed code review feedback - use counter instead of testing g_fSuspensionPending directly.

Commit migrated from dotnet/coreclr@a7678f5
MichalStrehovsky pushed a commit to MichalStrehovsky/corert that referenced this pull request Mar 31, 2020
* Changes to set gen0 bricks always. This reduces the time spent in find_first_object when finding the start of objects for marking interior pointers.

* Revert "Changes to set gen0 bricks always. This reduces the time spent in find_first_object when finding the start of objects for marking interior pointers."

This reverts commit dotnet/coreclr@9d53ff9.

* Two fixes to speed up suspension for foreground GCs while background GC is in progress:

- In background_mark_simple1, check g_fSuspensionPending and if it is set, save the state of the work and restart the loop - this will call allow_fgc() and thus allow a foreground GC to take place.

- In revisit_written_page, call allow_fgc() at the end - this allow a foreground GC to happen whenever we are done with revisiting a written page.

* Addressed code review feedback - use counter instead of testing g_fSuspensionPending directly.

Commit migrated from dotnet/coreclr@a7678f5
jkotas pushed a commit to dotnet/corert that referenced this pull request Apr 1, 2020
* Changes to set gen0 bricks always. This reduces the time spent in find_first_object when finding the start of objects for marking interior pointers.

* Revert "Changes to set gen0 bricks always. This reduces the time spent in find_first_object when finding the start of objects for marking interior pointers."

This reverts commit dotnet/coreclr@9d53ff9.

* Two fixes to speed up suspension for foreground GCs while background GC is in progress:

- In background_mark_simple1, check g_fSuspensionPending and if it is set, save the state of the work and restart the loop - this will call allow_fgc() and thus allow a foreground GC to take place.

- In revisit_written_page, call allow_fgc() at the end - this allow a foreground GC to happen whenever we are done with revisiting a written page.

* Addressed code review feedback - use counter instead of testing g_fSuspensionPending directly.

Commit migrated from dotnet/coreclr@a7678f5
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants