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

feat(coverage): caching for coverage #9366

Draft
wants to merge 24 commits into
base: master
Choose a base branch
from
Draft

Conversation

yash-atreya
Copy link
Member

@yash-atreya yash-atreya commented Nov 20, 2024

Motivation

Closes #8840.
Closes: Separate directory for artifacts generated by coverage.
Closes: Enable caching for coverage

Addresses #8840 (comment).
Somewhat addresses #8904 + #8889 - by enabling cache and avoiding recompilation

Solution

  • Add a warning that optimizer settings have been disabled.
  • Write coverage and build-info artifacts to out/coverage and out/coverage/build-info.
  • Write compiler cache to cache/coverage/
  • Enabling caching for coverage artifacts to avoid recompilation

@yash-atreya yash-atreya marked this pull request as draft November 21, 2024 09:16
@yash-atreya yash-atreya marked this pull request as ready for review November 21, 2024 18:30
@yash-atreya yash-atreya requested a review from klkvr November 21, 2024 18:38
@yash-atreya yash-atreya changed the title fix(coverage): write coverage artifacts to separate dir fix(coverage): separate dir + caching for coverage artifacts Nov 21, 2024
@yash-atreya yash-atreya enabled auto-merge (squash) November 21, 2024 18:38
@klkvr
Copy link
Member

klkvr commented Nov 21, 2024

did you test that coverage is collected correctly even after multiple different builds? it doesn't look like we account for different source_ids here

@yash-atreya yash-atreya marked this pull request as draft November 22, 2024 13:54
auto-merge was automatically disabled November 22, 2024 13:54

Pull request was converted to draft

@yash-atreya yash-atreya self-assigned this Nov 25, 2024
@yash-atreya yash-atreya added this to the v1.0.0 milestone Nov 25, 2024
@yash-atreya
Copy link
Member Author

Update:

In the previous implementation, we always recompiled the sources when running forge coverage. This would overwrite the artifact, keeping source_id's in order.

However, now that we have enabled caching, we cannot assume that source_id's are always in order.

Issue demonstrated by test here: e90a354

Next step to tackle this is to make coverage smarter by accounting for artifact.build_id and source_id e.g. the mapping of source_id => source should be changed to (build_id, source_id) => source`. This preserves coverage across recompilation and caching.

* fix: use `SourceIdentifier` in SourceFiles mapping

* fix(`coverage`): use `SourceIdentifier` in analysis and report.

* fix

* nit

* nit
@yash-atreya
Copy link
Member Author

did you test that coverage is collected correctly even after multiple different builds? it doesn't look like we account for different source_ids here

@klkvr ptal #9418 addresses this. Accounting for differing source_id's by taking build_id into consideration.

@yash-atreya yash-atreya marked this pull request as ready for review November 27, 2024 10:39
Copy link
Member

@klkvr klkvr left a comment

Choose a reason for hiding this comment

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

we should get rid of indexing by compiler version which was a workaround before we had build_id, including its usage in ContractId

this also does not correctly handle build_ids when processing hitmaps

when we identify a bytecode, we receipt ArtifactId which contains a build_id we should respect vs just the source_id

crates/evm/coverage/src/lib.rs Outdated Show resolved Hide resolved
crates/evm/coverage/src/anchors.rs Outdated Show resolved Hide resolved
@grandizzy grandizzy marked this pull request as draft November 28, 2024 12:06
@yash-atreya yash-atreya marked this pull request as ready for review November 29, 2024 13:20
@yash-atreya yash-atreya requested a review from klkvr November 29, 2024 13:20
@yash-atreya yash-atreya changed the title fix(coverage): separate dir + caching for coverage artifacts fix(coverage): caching for coverage Nov 29, 2024
@yash-atreya yash-atreya changed the title fix(coverage): caching for coverage feat(coverage): caching for coverage Nov 29, 2024
@yash-atreya yash-atreya enabled auto-merge (squash) November 29, 2024 13:21
crates/evm/coverage/src/lib.rs Outdated Show resolved Hide resolved
.and_then(|items| items.get_mut(anchor.item_id))
.get_mut(&contract_id.source_id)
.and_then(|items| {
let scaled_item_id = anchor.item_id % items.len();
Copy link
Member

Choose a reason for hiding this comment

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

what is this for?

Copy link
Member

Choose a reason for hiding this comment

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

this doesn't look correct. right now items are keyed by the source_id they are from but this tries to get it by the source id of the contract where anchor was found

/// All item anchors for the codebase, keyed by their contract ID.
pub anchors: HashMap<ContractId, (Vec<ItemAnchor>, Vec<ItemAnchor>)>,
/// All the bytecode hits for the codebase.
pub bytecode_hits: HashMap<ContractId, HitMap>,
/// The bytecode -> source mappings.
pub source_maps: HashMap<ContractId, (SourceMap, SourceMap)>,
/// Anchor Item ID by source ID
pub item_ids_by_source_id: HashMap<SourceIdentifier, Vec<usize>>,
Copy link
Member

Choose a reason for hiding this comment

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

this seems unused?

/// All coverage items for the codebase, keyed by the compiler version.
pub items: HashMap<Version, Vec<CoverageItem>>,
pub items: HashMap<SourceIdentifier, Vec<CoverageItem>>,
Copy link
Member

Choose a reason for hiding this comment

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

this should now be a Vec<CoverageItem> I guess given that we no longer have a version-level separation

}

let anchors = artifacts
.par_iter()
.filter(|artifact| sources.sources.contains_key(&artifact.contract_id.source_id))
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
.filter(|artifact| sources.sources.contains_key(&artifact.contract_id.source_id))

this should not be needed anymore

@yash-atreya yash-atreya disabled auto-merge December 2, 2024 11:46
@yash-atreya yash-atreya marked this pull request as draft December 2, 2024 11:46
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
Status: Todo
Development

Successfully merging this pull request may close these issues.

chore: warn optimization is disabled when forge coverage is called
2 participants