Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Replace ExecutionStatePool with ObjectPool #608

Merged
merged 9 commits into from
Mar 9, 2022
Merged

Replace ExecutionStatePool with ObjectPool #608

merged 9 commits into from
Mar 9, 2022

Conversation

yperbasis
Copy link
Member

No description provided.

@codecov
Copy link

codecov bot commented Mar 8, 2022

Codecov Report

Merging #608 (e630fc6) into master (5b65bd5) will decrease coverage by 0.00%.
The diff coverage is 97.43%.

Impacted file tree graph

@@            Coverage Diff             @@
##           master     #608      +/-   ##
==========================================
- Coverage   81.75%   81.75%   -0.01%     
==========================================
  Files         169      167       -2     
  Lines       13958    13947      -11     
==========================================
- Hits        11411    11402       -9     
+ Misses       2547     2545       -2     
Impacted Files Coverage Δ
core/silkworm/consensus/engine.hpp 100.00% <ø> (ø)
core/silkworm/execution/analysis_cache.cpp 100.00% <ø> (ø)
core/silkworm/execution/analysis_cache.hpp 100.00% <ø> (ø)
core/silkworm/execution/evm.hpp 80.00% <ø> (ø)
node/silkworm/stagedsync/stage_execution.cpp 34.12% <0.00%> (ø)
node/silkworm/stagedsync/stage_execution.hpp 100.00% <ø> (ø)
core/silkworm/common/object_pool.hpp 100.00% <100.00%> (ø)
core/silkworm/execution/evm.cpp 96.68% <100.00%> (+0.60%) ⬆️
core/silkworm/consensus/base/engine.cpp 93.03% <0.00%> (-1.00%) ⬇️
core/silkworm/trie/hash_builder.cpp 99.29% <0.00%> (-0.71%) ⬇️
... and 3 more

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 5b65bd5...e630fc6. Read the comment docs.

using ptr_t = std::unique_ptr<T, TDtor>;

ObjectPool() = default;
explicit ObjectPool(bool thread_safe = false) : thread_safe_{thread_safe} {}
Copy link
Contributor

Choose a reason for hiding this comment

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

if there a location where ObjectPool is created with thread_safe=true?

Copy link
Member Author

Choose a reason for hiding this comment

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

Yes, in cmd/test/consensus.

EvmHost host{*this};

gsl::owner<EvmoneExecutionState*> state{acquire_state()};
Copy link
Member

@mriccobene mriccobene Mar 9, 2022

Choose a reason for hiding this comment

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

Before unique_ptr did protect the life of the pointed object in case of an exception, gsl::owner doesn't do that.

Why did you replace unique_ptr with gsl::owner? had you been forced by ObjectPool interface?
In the next comment I sketch an ObjectPool interface that let's us use unique_ptr

Copy link
Member Author

@yperbasis yperbasis Mar 9, 2022

Choose a reason for hiding this comment

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

PR #605 dropped unique_ptr from ObjectPool. This PR simply uses gsl::owner to formalize the changes introduced by PR #605.


void add(T*& t) {
void add(gsl::owner<T*> t) {
SILKWORM_DETAIL_OBJECT_POOL_GUARD
Copy link
Member

Choose a reason for hiding this comment

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

There is another way to implement this:

  • we can add a mutex-type parameter to the template
template <class T, class M, class TDtor = std::default_delete<T>>
class ObjectPool {
   ...

   mutable M mutex_;
}

so the user can use a real mutex or a null_mutex (whose methods do nothing)

  • then code the methods usually
void add(gsl::owner<T*> t) {
    std::unique_lock lock(mutex_);
    ...
}

The only problem is that standard library lacks null_mutex, it is present in boost.

Copy link
Member Author

Choose a reason for hiding this comment

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

The reason I didn't add an extra template parameter is because I don't want to templatize EVM.

ObjectPool<EvmoneExecutionState>* state_pool{nullptr}; 

is fully specialized there.

if (pool_.empty()) {
return nullptr;
}
T* ret(pool_.top().release());
gsl::owner<T*> ret(pool_.top().release());
Copy link
Member

Choose a reason for hiding this comment

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

I think the ObjectPool can be improved if we use unique_ptr not only inside but also outside so that no leak can happen neither by forgetfulness nor by exception. (Or maybe we do not want to address this case because we have less or no function throwing exception).

Sorry for not saying this before but I have just realized it here seeing that you have been forced to replace unique_ptr with gsl::owner in the methods implementations (see my next comment).

This is a sample implementation returning and accepting unique_ptr:

template <class T>  // sample implementation
class ObjectPool {
  public:
    using ptr_t = std::unique_ptr<T>;

    explicit ObjectPool() {}

    void add(ptr_t t) {  // the user is forced to do a move here, i.e. transfer ownership
        pool_.push(std::move(t));
    }

    ptr_t acquire() {
        if (pool_.empty()) {
            return nullptr;
        }
        ptr_t ret;
        swap(ret, pool_.top());
        pool_.pop();
        return ret;  // transfer ownership
    }

  private:
    std::stack<ptr_t, std::vector<ptr_t>> pool_{};
};

So the usage becomes:

    auto resource = pool.acquire();
    ...
    pool.add(std::move(resource));

Copy link
Member Author

Choose a reason for hiding this comment

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

std::unique_ptr is probably a good fit for the use of ObjectPool for evm states, but it might be a bad fit for its use in node/silkworm/db/mdbx.cpp. Prior to PR #605 ObjectPool was actually using std::unique_ptr. In this PR I'm simply using gsl::owner for formalization of the changes made in PR #605.

Copy link
Member Author

Choose a reason for hiding this comment

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

And core doesn't use exceptions, so no need to worry about them.

@yperbasis yperbasis merged commit c25a57e into master Mar 9, 2022
@yperbasis yperbasis deleted the state_pool branch March 9, 2022 16:10
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants