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

Cache the 'row_type' on TableSchema so is not re-build in each access #638

Merged
merged 1 commit into from
Dec 8, 2023

Conversation

mamcx
Copy link
Contributor

@mamcx mamcx commented Dec 6, 2023

Description of Changes

This is a possible fix for the performance issue on BitCraft.

Now is forbidden to mutate the columns on TableSchema so we can cache the row_type.

Expected complexity level and risk

1

@mamcx mamcx requested a review from jdetter December 6, 2023 23:53
@mamcx mamcx self-assigned this Dec 6, 2023
Copy link
Contributor

@cloutiertyler cloutiertyler left a comment

Choose a reason for hiding this comment

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

Please leave a comment explaining what the purpose of the new function is (to cache the row_type) and why it is important to cache the row_type

table_id: TableId(42),
table_name: "Person".into(),
columns: vec![ColumnSchema {
let current = vec![Cow::Owned(TableSchema::new(
Copy link
Contributor

Choose a reason for hiding this comment

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

Let's keep this PR as minimal as possible. Please remove the changes related to this.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I need to do this change to calculate the row_type

})
.collect(),
)
pub fn get_row_type(&self) -> &ProductType {
Copy link
Contributor

Choose a reason for hiding this comment

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

Please leave a comment on this code explaining what it's purpose is and why we are caching the product_type

table_type: StTableType,
table_access: StAccess,
) -> Self {
let row_type = ProductType::new(
Copy link
Contributor

Choose a reason for hiding this comment

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

I see, it's related to caching the row type.

@mamcx
Copy link
Contributor Author

mamcx commented Dec 7, 2023

benchmark please

Centril
Centril previously requested changes Dec 7, 2023
@@ -271,7 +271,7 @@ impl CommittedState {
// Insert the columns into `st_columns`
let st_columns = self.get_or_create_table(ST_COLUMNS_ID, st_columns_schema());

for col in system_tables().into_iter().flat_map(|x| x.columns) {
for col in system_tables().into_iter().flat_map(|x| x.columns.clone()) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Why is this cloning now? You already have an owned type due to into_iter.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Rust complains:

error[E0507]: cannot move out of dereference of `spacetimedb_sats::db::def::TableSchema`
   --> crates/core/src/db/datastore/locking_tx_datastore/mod.rs:274:61
    |
274 |         for col in system_tables().into_iter().flat_map(|x| x.columns) {
    |                                                             ^^^^^^^^^ move occurs because value has type `std::vec::Vec<spacetimedb_sats::db::def::ColumnSchema>`, which does not implement the `Copy` trait

I think this is a consequence of the read_only mark.

Copy link
Contributor

Choose a reason for hiding this comment

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

Ah, well in that case I think the attribute should be removed.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The issue is that caching the row_type means any change to columns invalidates that, and I need a way to protect against that scenario.

Copy link
Contributor

Choose a reason for hiding this comment

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

You can make the columns field non-pub in that case and provide methods that give self and &self access but not &mut self.

crates/sats/src/db/def.rs Outdated Show resolved Hide resolved
crates/sats/src/db/def.rs Outdated Show resolved Hide resolved
self.schema_for_table(table_id, database_address)?.get_row_type(),
self.schema_for_table(table_id, database_address)?
.get_row_type()
.clone(),
Copy link
Contributor

Choose a reason for hiding this comment

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

schema_for_table' Cow::Borrowed branch should be unreachable here because the if let Some(row_type) branch wasn't taken. At any rate, you can avoid this clone by checking if we have Cow::Owned.

))
Ok(match self.schema_for_table(table_id, database_address)? {
Cow::Borrowed(x) => Cow::Borrowed(x.get_row_type()),
Cow::Owned(x) => Cow::Owned(x.get_row_type().clone()),
Copy link
Contributor

Choose a reason for hiding this comment

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

clone shouldn't be necessary in the Owned branch either.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This is get_row_type(&self) -> &ProductType

Copy link
Contributor

Choose a reason for hiding this comment

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

Yeah but you have ownership of TableSchema, so you could get out an owned ProductType, either through adding an additional method or by making the field pub.

@mamcx mamcx force-pushed the mamcx/perf-multi-column branch from 5c08141 to c1f1148 Compare December 8, 2023 13:34
Copy link
Contributor

@cloutiertyler cloutiertyler left a comment

Choose a reason for hiding this comment

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

LGTM

@cloutiertyler cloutiertyler dismissed Centril’s stale review December 8, 2023 22:22

I'm dismissing this because the comments appear to me to have been addressed.

@cloutiertyler cloutiertyler merged commit 683a803 into master Dec 8, 2023
5 checks passed
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