Skip to content

Conversation

jonasschnelli
Copy link
Contributor

During the GUI startup, there is currently an accumulation of cs_main locks due to setting initial chain state values at multiple locations (in the GUI main thread).

This PR tries to cache the initial chain state (tip height, tip time, best header, etc.) short after loading the blockindex.

The cached values are then used instead of fetching them again (and thus locking cs_main) during setting the client model.

This should fix the initial GUI blocking often experienced during or short after the splashscreen.
On mac, best tested together with #19007.

@ryanofsky
Copy link
Contributor

Concept ACK and approach half-ACK. This seems like a good change to make with the caveat that it shouldn't be necessary to add new global NodeContext variables and add new node initialization and caching code to fix a GUI problem.

Instead of having AppInitMain set global variables in NodeContext that get returned by a new Node::getInitialChainState method, and having the node cache information about itself on behalf of the GUI, I think the GUI should be able to query the node at the right time and pass the information where it needs to go during its initialization.

This would mean instead of having a new Node::getInitialChainState method returning cached information, there would be a new Node::getBlockTip method [1] returning live information. The GUI could call this right after it calls Node::appInitMain, and pass the returned values along to setClientModel. It might also be good to define a BlockTip struct to avoid repeating the same function arguments multiple places.

[1] Suggesting getBlockTip as a method name to be consistent with other existing method names: getHeaderTip, handleNotifyBlockTip, handleNotifyHeaderTip as well as the new struct BlockTip from #17993

@DrahtBot
Copy link
Contributor

DrahtBot commented May 18, 2020

The following sections might be updated with supplementary metadata relevant to reviewers and maintainers.

Conflicts

Reviewers, this pull request conflicts with the following ones:

If you consider this pull request important, please also help to review the conflicting pull requests. Ideally, start with the one that should be merged first.

@jonasschnelli
Copy link
Contributor Author

This would mean instead of having a new Node::getInitialChainState method returning cached information, there would be a new Node::getBlockTip method [1] returning live information. The GUI could call this right after it calls Node::appInitMain, and pass the returned values along to setClientModel. It might also be good to define a BlockTip struct to avoid repeating the same function arguments multiple places.

I thought about this and agree that this PRs solution might not be very elegant.

The approach you described should work,.. the main difference is that the networking is running then already which might lead to additional cs_main locking (within this PR, we fetch the information before we start the networking). Your approach would also require at least another locking of cs_main (right?).

What I was looking for was using an existing cs_main lock to gather the information required for the GUI (avoid collecting the same information into concurrency-safe primitives over and over).

@ryanofsky
Copy link
Contributor

ryanofsky commented May 19, 2020

The approach you described should work,.. the main difference is that the networking is running then already which might lead to additional cs_main locking (within this PR, we fetch the information before we start the networking). Your approach would also require at least another locking of cs_main (right?).

Oh, I thought I might have been missing something. Now I understand why this is saving tip information inside AppInitMain. I think you're right that there is a possibility of cs_main blocking if information is retrieved after the AppInitMain call instead of during it (though in this case it still wouldn't be happening on the qt event loop thread, so might not be an actual problem).

If this is a problem, it could be solved most directly by having AppInitMain just return tip information, instead of stashing it into a global struct to be retrieved later. Using something like struct BlockTip from #17993 and having AppInitMain take an optional BlockTip* output argument would be a pretty clean way for it to return information.

@jonasschnelli jonasschnelli force-pushed the 2020/05/guilocks branch 3 times, most recently from 2cf87fe to 4ef682a Compare May 19, 2020 13:20
@jonasschnelli
Copy link
Contributor Author

Thanks for the feedback @ryanofsky.
I tried to implement your approach without the global struct.

Copy link
Contributor

@ryanofsky ryanofsky left a comment

Choose a reason for hiding this comment

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

Code review ACK 4ef682a. Works exactly as discussed, no issues at all that I could see

@jonasschnelli
Copy link
Contributor Author

Force pushed a fix for the qt test apptests (missed the new qRegisterMetaType<interfaces::BlockAndHeaderTipInfo>("interfaces::BlockAndHeaderTipInfo").

Copy link
Contributor

@ryanofsky ryanofsky left a comment

Choose a reason for hiding this comment

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

Code review ACK ded3edd. Just apptests type registration added since last review

@@ -66,6 +66,7 @@ void AppTests::appTests()
ECC_Stop(); // Already started by the common test setup, so stop it to avoid interference
LogInstance().DisconnectTestLogger();

qRegisterMetaType<interfaces::BlockAndHeaderTipInfo>("interfaces::BlockAndHeaderTipInfo");
Copy link
Contributor

Choose a reason for hiding this comment

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

In commit "Reduce cs_main lock accumulation during GUI startup" (ded3edd)

I guess it'd be nice to register types in a common location in the future to avoid the need to do this twice

Copy link
Contributor

Choose a reason for hiding this comment

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

Agree, suggestion GUIUtils::registerMetaTypes or something like that.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes. Lets do this later when more registration are required/appear.

@jonasschnelli
Copy link
Contributor Author

Rebased (due to #18740).

Copy link
Contributor

@promag promag left a comment

Choose a reason for hiding this comment

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

Concept ACK.

src/init.cpp Outdated
tip_info->verification_progress = GuessVerificationProgress(Params().TxData(), ::ChainActive().Tip());
}
if (tip_info && ::pindexBestHeader) {
tip_info->header_height = ::pindexBestHeader->nHeight;;
Copy link
Contributor

Choose a reason for hiding this comment

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

nit double ;

@@ -66,6 +66,7 @@ void AppTests::appTests()
ECC_Stop(); // Already started by the common test setup, so stop it to avoid interference
LogInstance().DisconnectTestLogger();

qRegisterMetaType<interfaces::BlockAndHeaderTipInfo>("interfaces::BlockAndHeaderTipInfo");
Copy link
Contributor

Choose a reason for hiding this comment

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

Agree, suggestion GUIUtils::registerMetaTypes or something like that.

Copy link
Contributor

@ryanofsky ryanofsky left a comment

Choose a reason for hiding this comment

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

Code review ACK bf788c7. No changes since last review other than rebase

Copy link
Contributor

@promag promag left a comment

Choose a reason for hiding this comment

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

Rebased here aa70cc8, also dropped extra ;.

@jonasschnelli
Copy link
Contributor Author

Rebased and removed the extra ;

Copy link
Contributor

@ryanofsky ryanofsky left a comment

Choose a reason for hiding this comment

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

Code review ACK 43ef1f3. No changes since last review other than rebase (qmetatype conflict) and removing double semicolon

@jonasschnelli
Copy link
Contributor Author

Rebased.

Copy link
Contributor

@ryanofsky ryanofsky left a comment

Choose a reason for hiding this comment

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

Code review ACK 386ec19. Just rebased since last review due to conflicts

@promag
Copy link
Contributor

promag commented Aug 13, 2020

Code review ACK 386ec19.

@jonatack
Copy link
Member

Concept ACK

@jonasschnelli jonasschnelli merged commit 1052b09 into bitcoin:master Aug 13, 2020
Fabcien pushed a commit to Bitcoin-ABC/bitcoin-abc that referenced this pull request Jul 6, 2021
Summary:
PR description: Reduce cs_main lock accumulation during GUI startup
> During the GUI startup, there is currently an accumulation of cs_main locks due to setting initial chain state values at multiple locations (in the GUI main thread).
>
> This PR tries to cache the initial chain state (tip height, tip time, best header, etc.) short after loading the blockindex.
>
> The cached values are then used instead of fetching them again (and thus locking cs_main) during setting the client model.
>
> This should fix the initial GUI blocking often experienced during or short after the splashscreen.

This is a backport of [[bitcoin/bitcoin#19011 | core#19011]] [1/4]
bitcoin/bitcoin@25e1d0b

Test Plan: `ninja all check-all`

Reviewers: #bitcoin_abc, Fabien

Reviewed By: #bitcoin_abc, Fabien

Differential Revision: https://reviews.bitcoinabc.org/D9734
Fabcien pushed a commit to Bitcoin-ABC/bitcoin-abc that referenced this pull request Jul 6, 2021
Summary:
PR description:
> During the GUI startup, there is currently an accumulation of cs_main locks due to setting initial chain state values at multiple locations (in the GUI main thread).
>
> This PR tries to cache the initial chain state (tip height, tip time, best header, etc.) short after loading the blockindex.
>
> The cached values are then used instead of fetching them again (and thus locking cs_main) during setting the client model.
>
> This should fix the initial GUI blocking often experienced during or short after the splashscreen.

bitcoin/bitcoin@b354a14
> Add BlockAndHeaderTipInfo to the node interface/appInit

bitcoin/bitcoin@d42cb79
> Optionally populate BlockAndHeaderTipInfo during AppInitMain

This is a backport of [[bitcoin/bitcoin#19011 | core#19011]] [2&3/4]
The commits needed squashing because the first one alone breaks the build.

Depends on D9734

Test Plan: `ninja all check-all`

Reviewers: #bitcoin_abc, Fabien

Reviewed By: #bitcoin_abc, Fabien

Differential Revision: https://reviews.bitcoinabc.org/D9735
Fabcien pushed a commit to Bitcoin-ABC/bitcoin-abc that referenced this pull request Jul 6, 2021
Summary:
PR description:
> During the GUI startup, there is currently an accumulation of cs_main locks due to setting initial chain state values at multiple locations (in the GUI main thread).
>
> This PR tries to cache the initial chain state (tip height, tip time, best header, etc.) short after loading the blockindex.
>
> The cached values are then used instead of fetching them again (and thus locking cs_main) during setting the client model.
>
> This should fix the initial GUI blocking often experienced during or short after the splashscreen.

This concludes backport of [[bitcoin/bitcoin#19011 | core#19011]] [4/4]
bitcoin/bitcoin@386ec19

Depends on D9735
Depends on D9737

Test Plan: `ninja all check-all`

Reviewers: #bitcoin_abc, majcosta

Reviewed By: #bitcoin_abc, majcosta

Subscribers: Fabien

Differential Revision: https://reviews.bitcoinabc.org/D9736
@bitcoin bitcoin locked as resolved and limited conversation to collaborators Feb 15, 2022
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.

5 participants