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

SVM: remove usage of program cache from load_program_with_pubkey() #1582

Merged
merged 2 commits into from
Jun 4, 2024

Conversation

pgarg66
Copy link

@pgarg66 pgarg66 commented Jun 3, 2024

Problem

Use of ProgramCache in load_program_with_pubkey() can be removed. It's mainly used to get the instance of RuntimeEnvironments. That can instead be supplied by the caller. Relaxing this dependency will reduce call sites outsize SVM where ProgramCache is being referenced.

Summary of Changes

  • Add accessor in TransactionBatchProcessor to get the RuntimeEnvironments for a given epoch
  • Pass the environments to load_program_with_pubkey(), removing the need for ProgramCache
  • Update unit tests

Fixes #

buffalojoec
buffalojoec previously approved these changes Jun 4, 2024
Comment on lines 199 to 200
.get_environments_for_epoch(epoch)
.clone()
Copy link

Choose a reason for hiding this comment

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

I think you can move the clone directly to ProgramCache get_environmens_for_epoch directly. It is only used in two places and all of them need a clone.

Copy link
Author

Choose a reason for hiding this comment

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

Good advice. I'll update the PR.

callbacks: &CB,
program_cache: &ProgramCache<FG>,
environments: &ProgramRuntimeEnvironments,
Copy link

Choose a reason for hiding this comment

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

I think this argument does not need to be a reference. Inside this function's match arm, we clone the environments. I believe that if we move this parameter, we don't need to clone the environments, moving them instead.

PS: When I say move, please think about moving memory as opposed to Rust's cloning.

Copy link
Author

Choose a reason for hiding this comment

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

Removing the reference won't help much with removing the clone(). The unwrap_or_else() uses the environments and requires prior use of environments to be cloned.

I think keeping the reference here is better. Current users of load_program_with_pubkey() are ok with move as the environments is not referenced at the call site after calling this function. But, this is a public function. Other users may require to hold on to the environments, and it would force them to clone() it before calling this function.

Copy link

@buffalojoec buffalojoec left a comment

Choose a reason for hiding this comment

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

Sorry guys, but I'm actually a little confused as to why we need the clone at all in either method.

As far as I can tell, the argument is a reference - &ProgramRuntimeEnvironments - in every function signature called by the lines changed in this PR.

In my opinion, let both the SVM's and the cache's get_environments_for_epoch return a reference, and clone only where ownership is explicitly required. This seems to be all within tests, except for program cache's new_from_cache, which is explicitly intentional.

@pgarg66
Copy link
Author

pgarg66 commented Jun 4, 2024

Sorry guys, but I'm actually a little confused as to why we need the clone at all in either method.

As far as I can tell, the argument is a reference - &ProgramRuntimeEnvironments - in every function signature called by the lines changed in this PR.

In my opinion, let both the SVM's and the cache's get_environments_for_epoch return a reference, and clone only where ownership is explicitly required. This seems to be all within tests, except for program cache's new_from_cache, which is explicitly intentional.

SVM's get_environments_for_epoch() cannot return a reference due to lifetime issues. The read lock of program cache gets dropped when the function returns, and causes the lifetime of inner reference to go out of scope.

The structure carries two Arc<>. So clone of struct is not expensive.

@buffalojoec
Copy link

SVM's get_environments_for_epoch() cannot return a reference due to lifetime issues. The read lock of program cache gets dropped when the function returns, and causes the lifetime of inner reference to go out of scope.

The structure carries two Arc<>. So clone of struct is not expensive.

Ahh, okay this was what I was missing. I still prefer the clone at the SVM-level, but I'll leave up to you two.

@pgarg66
Copy link
Author

pgarg66 commented Jun 4, 2024

SVM's get_environments_for_epoch() cannot return a reference due to lifetime issues. The read lock of program cache gets dropped when the function returns, and causes the lifetime of inner reference to go out of scope.
The structure carries two Arc<>. So clone of struct is not expensive.

Ahh, okay this was what I was missing. I still prefer the clone at the SVM-level, but I'll leave up to you two.

Looks like all users of LoadedProgram's get_environments_for_epoch() are cloning the reference anyway. So, it should not cause any additional overheads.

@pgarg66 pgarg66 merged commit 9830fb6 into anza-xyz:master Jun 4, 2024
42 checks passed
@pgarg66 pgarg66 deleted the svm branch June 4, 2024 21:44
@@ -416,10 +424,9 @@ impl<FG: ForkGraph> TransactionBatchProcessor<FG> {
// Load, verify and compile one program.
let program = load_program_with_pubkey(
callback,
&program_cache,
&self.get_environments_for_epoch(self.epoch),
Copy link

Choose a reason for hiding this comment

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

This introduces a nested read lock (because program_cache is already locked above) which is can cause a dead lock.

Copy link
Author

Choose a reason for hiding this comment

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

Yes, created this PR to address it: #1616

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.

4 participants