Skip to content
This repository has been 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

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
4 participants