Skip to content
This repository has been archived by the owner on Aug 2, 2022. It is now read-only.

Migrate fc::static_variant to std::variant #9235

Merged
merged 25 commits into from
Aug 25, 2020
Merged

Conversation

TimothyBanks
Copy link
Contributor

@TimothyBanks TimothyBanks commented Jun 22, 2020

Change Description

This PR is to replace the use of fc::static_variant with std::variant. Based on performance metrics, std::variant is the better alternative.

Jira: https://blockone.atlassian.net/browse/EPE-17
Jira issue has links to benchmarks describing performance improvement of std::variant over fc::static_variant.

Change Type

Select ONE

  • Documentation
  • Stability bug fix
  • Other
  • Other - special case

Consensus Changes

  • Consensus Changes

API Changes

  • API Changes

Documentation Additions

  • Documentation Additions

@heifner
Copy link
Contributor

heifner commented Jun 22, 2020

Can we get a better description on this PR please. The standard template should be used. Specifically the check box sections are needed.
Also, when we stop using JIRA again we will have no information on this change.

@TimothyBanks
Copy link
Contributor Author

This PR should be ready for review now.

I am currently unsure which boxes need to be check in the description.

Copy link
Contributor

@allenhan2 allenhan2 left a comment

Choose a reason for hiding this comment

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

std::get throws different exception from fc::static_variants, please check the exception handling has been updated or added handling for that.
exception handling is my biggest concern, and not much code coverage there. It may change the error handling path and error log printing.

libraries/fc/include/fc/static_variant.hpp Outdated Show resolved Hide resolved
libraries/fc/include/fc/static_variant.hpp Outdated Show resolved Hide resolved
libraries/fc/include/fc/static_variant.hpp Outdated Show resolved Hide resolved
@TimothyBanks
Copy link
Contributor Author

PR is updated.

@TimothyBanks
Copy link
Contributor Author

TimothyBanks commented Jun 25, 2020

I'm open to suggestions as to what to call it. Or I can just call it get.

Copy link
Contributor

@allenhan2 allenhan2 left a comment

Choose a reason for hiding this comment

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

std::visit has similar issue as std::get,
fc::static_variant throws fc exception, std::visit throws std::bad_variant_access.

Also, std::get, if it is not guarded with check, please use fc::get, so when people copy the code or make change later on, std::get won't be miss-used without checking.

libraries/chain/controller.cpp Show resolved Hide resolved
libraries/chain/controller.cpp Show resolved Hide resolved
libraries/chain/controller.cpp Show resolved Hide resolved
libraries/chain/controller.cpp Show resolved Hide resolved
libraries/chain/controller.cpp Show resolved Hide resolved
libraries/chain/include/eosio/chain/block.hpp Show resolved Hide resolved
libraries/chain/include/eosio/chain/block.hpp Show resolved Hide resolved
@TimothyBanks
Copy link
Contributor Author

TimothyBanks commented Jun 26, 2020

Can you please show me where this new exception type is going to cause problems in the system? I'm adding overhead to the use of std::variant just to maintain throwing the same exception which seems a bit overkill. In the case of using std::get, I thought it was a good compromise to invoke std::get_if and if that fails, then throw a new exception. In the case of std::visit, I don't have a conditional equivalent and I don't like adding the overhead of another try/catch block just to repackage the exception that is bubbling out.

I would much prefer to update the parts of the system that are expecting this exact fc exception message to be thrown and move them over to the std equivalent.

@allenhan2
Copy link
Contributor

Can you please show me where this new exception type is going to cause problems in the system? I'm adding overhead to the use of std::variant just to maintain throwing the same exception which seems a bit overkill. In the case of using std::get, I thought it was a good compromise to invoke std::get_if and if that fails, then throw a new exception. In the case of std::visit, I don't have a conditional equivalent and I don't like adding the overhead of another try/catch block just to repackage the exception that is bubbling out.

I would much prefer to update the parts of the system that are expecting this exact fc exception message to be thrown and move them over to the std equivalent.

Can you please show me where this new exception type is going to cause problems in the system? I'm adding overhead to the use of std::variant just to maintain throwing the same exception which seems a bit overkill. In the case of using std::get, I thought it was a good compromise to invoke std::get_if and if that fails, then throw a new exception. In the case of std::visit, I don't have a conditional equivalent and I don't like adding the overhead of another try/catch block just to repackage the exception that is bubbling out.

I would much prefer to update the parts of the system that are expecting this exact fc exception message to be thrown and move them over to the std equivalent.

Appreciate your concern on the performance impact, however, logic correctness triumphs speed before we have good test coverage. The change should not jeopardize the error handling, which seems to me noway to verify.
For std::get, if it is not guarded with std::holds_alternative, please use fc::get, which will throw fc exception instead of std::exception.

@heifner
Copy link
Contributor

heifner commented Jun 26, 2020

I think if you eval everywhere std::variant is used and make sure exception handling does not introduce a change in behavior, then it would be really nice to complete remove dependency on anything in fc.

@TimothyBanks
Copy link
Contributor Author

TimothyBanks commented Jun 26, 2020

A quick survey of EOS (and submodules) shows only a couple of places that we explicitly catch the fc::assert_exception. Everywhere else is within tests. Are there any other places that I could check? Or is this too ignorant of an evaluation?

I guess you could be catching on a base type as well.

@TimothyBanks
Copy link
Contributor Author

TimothyBanks commented Jun 29, 2020

static_variant has been removed with the exception of a file named static_variant. It currently only holds functionality that is needed by EOS that isn't available with std::variant.

As for tracking down all code paths, I think everyone needs to come to an agreement on what is acceptable and what the path forward should be. @larryk85 Could you please chime in on this was well.

@TimothyBanks
Copy link
Contributor Author

Could we move the exception part into another JIRA issue and push this PR in?

@TimothyBanks
Copy link
Contributor Author

Updated.

@TimothyBanks
Copy link
Contributor Author

@heifner @allenhan2 Please review again.

throw;
} catch( const fc::exception& e ) {
handle_exception(e);
} catch ( const std::exception& e ) {
Copy link
Contributor

@heifner heifner Jul 30, 2020

Choose a reason for hiding this comment

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

Why was catch of std::exception added here? Do we really want all std::exceptions to be ignored? Either this is not needed OR this is a consensus change since nodes without this code will fail transaction differently.

Looking at this more, it is not necessarily a consensus change since std::variant can throw. My concern would be the use of something like std::vector::at() or some other throw of std::exception that would be handled differently now.

Copy link
Contributor

Choose a reason for hiding this comment

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

An argument can be made that exceptions from something like std::vector::at() should be captured here as you have it. However, this could potentially be a consensus change. I'll leave it up to @b1bart to indicate if he is comfortable with this change. I have NOT reviewed all exception code paths to determine how safe this is. This comment goes for all the exception handling changes in this PR (not just here).

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Would it be better to catch just the specific std errors being thrown by variant and optional? I can change the std::exception handler to std::bad_variant_access and whatever specific std exceptions that are thrown.

Copy link
Contributor

Choose a reason for hiding this comment

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

I think what you have is likely fine. I would only argue that someone does a thorough review of possible exceptions in code paths where this was added. I suspect there are not any other std exceptions we really need to worry about. So just need someone to review and give approval.

@heifner
Copy link
Contributor

heifner commented Jul 30, 2020

I think all the exception changes should be pulled out into a separate PR. They are very dangerous and deserve their own PR. If needed for the other changes then make sure it is called out in the PR description.

@TimothyBanks
Copy link
Contributor Author

Replay was successful.
https://buildkite.com/EOSIO/auto-eosio-full-replay-test/builds/245#_
https://buildkite.com/EOSIO/auto-eosio-replay-test/builds/246
Merging develop now.

Please take one last look.

@TimothyBanks
Copy link
Contributor Author

@heifner @allenhan2 I think this is ready to go. Please take another look.

@TimothyBanks TimothyBanks merged commit 9eaa571 into develop Aug 25, 2020
@TimothyBanks TimothyBanks deleted the EPE-17-develop-variant branch August 25, 2020 23:42
swatanabe pushed a commit to eosnetworkfoundation/mandel that referenced this pull request Jan 28, 2022
Cherry-picked from 9eaa571 (EOSIO/eos#9235) with additional fixes for later changes to 2.0.x.
swatanabe added a commit to eosnetworkfoundation/mandel that referenced this pull request Jan 28, 2022
Cherry-picked from 9eaa571 (EOSIO/eos#9235) with additional fixes for later changes to 2.0.x.
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants