Skip to content

feat: CAR-backed Blockstore - #3085

Merged
aatifsyed merged 27 commits into
mainfrom
aatifsyed/read-cars
Jun 29, 2023
Merged

feat: CAR-backed Blockstore#3085
aatifsyed merged 27 commits into
mainfrom
aatifsyed/read-cars

Conversation

@aatifsyed

@aatifsyedaatifsyed commented Jun 27, 2023

Copy link
Copy Markdown
Contributor

Summary of changes

Work for #3074.

I've not wrapped a Blockstore, opting to keep a write_cache instead for simplicity.
Is this appropriate for the intended usecase?

If not, I will probably create an inner ParityDb, backed by an anonymous file/directory, as that will be more appropriate for this usecase (users shouldn't have to configure a database, or pick a directory, it's conceptually private to the CarBackedBlockstore.

Other information and links

Change checklist

  • I have performed a self-review of my own code,
  • I have made corresponding changes to the documentation,
  • I have added tests that prove my fix is effective or that my feature works (if possible),
  • I have made sure the CHANGELOG is up-to-date. All user-facing changes should be reflected in this document.
    • N/A

@ruseinovruseinov left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Looks good, left some thoughts and nits.

Comment threadsrc/car_backed_blockstore.rs
Comment threadsrc/car_backed_blockstore.rs
Comment threadsrc/car_backed_blockstore.rs Outdated
Comment threadsrc/car_backed_blockstore.rs Outdated
Comment threadsrc/car_backed_blockstore.rs Outdated
Comment threadsrc/car_backed_blockstore.rs Outdated
}

#[cfg(test)]
mod tests {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

For the sake of coverage, we could add cases for empty and corrupted CAR files.

@lemmihlemmih left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Love it. I changed forest-cli snapshot validate to use this code, and here are the numbers when validating a 36GiB snapshot:

 CarDB: total: 44s, indexing: 29s, walking: 15s
ParityDB: total: 171s, loading: 147s, walking: 24s

Results:

  • No wasted disk space. This blockstore doesn't require any disk space (as long as the CAR files are uncompressed).
  • Significantly faster load times: 29s vs 147s.
  • Significantly faster access times: 15s vs 24s to visit every node in the graph.

Future improvements:

  • The CarBackedBlockstore takes a buffered reader. This might not be the best option, especially when we know exactly how much to read after seeking.
  • The CIDs are not validated. The CarReader validates that the CIDs are correct. We should do the same (but in parallel).

This blockstore is a huge improvement for forest-cli snapshot validate. Let's use it immediately.

Comment threadsrc/car_backed_blockstore.rs
@aatifsyed
aatifsyed marked this pull request as draft June 28, 2023 10:53
@hanabi1224

Copy link
Copy Markdown
Contributor

How feasible is it to support multiple car files? I can think of a scenario that uses a subset car file of a snapshot and the manifest bundle car file (2 car files in total) to unit test state migration(s)

@lemmih

lemmih commented Jun 28, 2023

Copy link
Copy Markdown
Contributor

How feasible is it to support multiple car files? I can think of a scenario that uses a subset car file of a snapshot and the manifest bundle car file (2 car files in total) to unit test state migration(s)

The easiest way to handle that would be to concatenate the two CAR files.

# This adds the manifest key-value pairs to the snapshot.car file
cat manifest.car >> snapshot.car

@aatifsyed

Copy link
Copy Markdown
ContributorAuthor

The easiest way to handle that would be to concatenate the two CAR files.

From a code read, I'm not sure our current code handles, that, neither would this PR, but this could be a future enhancement.

Comment threadsrc/car_backed_blockstore.rs Outdated
@aatifsyedaatifsyed self-assigned this Jun 28, 2023
Comment threadsrc/car_backed_blockstore.rs
@aatifsyed
aatifsyedforce-pushed the aatifsyed/read-cars branch from a045c87 to 07b5d43CompareJune 28, 2023 22:36
/// [`Blockstore`] API calls may panic if this is not upheld.
/// - `reader`'s buffer should have enough room for the [`CarHeader`] and any [`Cid`]s.
#[tracing::instrument(level = "debug", skip_all)]
pub fn new(mut reader: ReaderT) -> cid::Result<Self> {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Would wrapping reader in a BufReader improve performance during the indexing?

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

I've tested a few buffer sizes, on a 36G snapshot and a 2.6G snapshot

$ du -h ...36G /home/aatif/chainsafe/snapshots/filecoin_full_calibnet_2023-04-07_450000.car2.6G /home/aatif/chainsafe/snapshots/forest_snapshot_calibnet_2023-06-29_height_690463.car

Large snapshot

Note there's a low confidence here - n=1

CommandMean [s]Min [s]Max [s]Relative
./target/release/examples/benchmark --mode buffer8k /home/aatif/chainsafe/snapshots/filecoin_full_calibnet_2023-04-07_450000.car226.545226.545226.5451.05
./target/release/examples/benchmark --mode buffer1k /home/aatif/chainsafe/snapshots/filecoin_full_calibnet_2023-04-07_450000.car237.063237.063237.0631.09
./target/release/examples/benchmark --mode buffer100 /home/aatif/chainsafe/snapshots/filecoin_full_calibnet_2023-04-07_450000.car216.535216.535216.5351.00
./target/release/examples/benchmark --mode unbuffered /home/aatif/chainsafe/snapshots/filecoin_full_calibnet_2023-04-07_450000.car234.794234.794234.7941.08

Small snapshot

Probably not worth a lot, because the OS will probably keep a hot cache of the file on disk

CommandMean [s]Min [s]Max [s]Relative
./target/release/examples/benchmark --mode buffer8k /home/aatif/chainsafe/snapshots/forest_snapshot_calibnet_2023-06-29_height_690463.car3.229 ± 0.2482.9463.6601.32 ± 0.13
./target/release/examples/benchmark --mode buffer1k /home/aatif/chainsafe/snapshots/forest_snapshot_calibnet_2023-06-29_height_690463.car2.443 ± 0.1482.2762.6681.00
./target/release/examples/benchmark --mode buffer100 /home/aatif/chainsafe/snapshots/forest_snapshot_calibnet_2023-06-29_height_690463.car2.562 ± 0.3052.1493.0431.05 ± 0.14
./target/release/examples/benchmark --mode unbuffered /home/aatif/chainsafe/snapshots/forest_snapshot_calibnet_2023-06-29_height_690463.car5.788 ± 0.1925.5736.1052.37 ± 0.16

Note that std::io::Seek::seek-ing on a std::io::BufReader always discards the buffer.

So maybe a small buffer is good for our use-case here? I'd say it's not clear, and I don't want to spend too much time benchmarking. Gonna have a 100 byte buffer and call it at that, please do double check my benchmarks if you've got time: here's the code 7a20c4c

@aatifsyedaatifsyedJun 29, 2023

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

CommandMean [s]Min [s]Max [s]Relative
buffer8k52.86152.15654.3171.02
buffer1k52.02851.45553.8801.00
buffer10053.52552.87755.1871.03
unbuffered85.45184.16687.1081.64

David did some benchmarking (n=10) on filecoin_full_calibnet_2023-04-07_450000.car - buffering is absolutely worth it

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Unabridged results over 10 runs:

CommandMean [s]Min [s]Max [s]Relative
./target/release/examples/benchmark --mode buffer8k ../lotus/filecoin_full_calibnet_2023-04-07_450000.car52.861 ± 0.58752.15654.3171.02 ± 0.02
./target/release/examples/benchmark --mode buffer1k ../lotus/filecoin_full_calibnet_2023-04-07_450000.car52.028 ± 0.68751.45553.8801.00
./target/release/examples/benchmark --mode buffer100 ../lotus/filecoin_full_calibnet_2023-04-07_450000.car53.525 ± 0.63852.87755.1871.03 ± 0.02
./target/release/examples/benchmark --mode unbuffered ../lotus/filecoin_full_calibnet_2023-04-07_450000.car85.451 ± 1.01184.16687.1081.64 ± 0.03

@aatifsyed
aatifsyedforce-pushed the aatifsyed/read-cars branch from c993d5e to d924693CompareJune 29, 2023 14:36
@aatifsyed
aatifsyed marked this pull request as ready for review June 29, 2023 14:36
@aatifsyed
aatifsyed requested a review from lemmihJune 29, 2023 14:58
@aatifsyed
aatifsyed enabled auto-merge (squash) June 29, 2023 15:24

@lemmihlemmih left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Lovely.

Sign up for freeto 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.

5 participants

@aatifsyed@hanabi1224@lemmih@ruseinov@LesnyRumcajs