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

introduce parallel salsa #568

Open
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

davidbarsky
Copy link
Contributor

Initial pass; very much not ready. Putting it up for initial feedback; I'm still figuring out how to wrap &Db reasonably.

Copy link

netlify bot commented Aug 23, 2024

Deploy Preview for salsa-rs canceled.

Name Link
🔨 Latest commit 0102ffb
🔍 Latest deploy log https://app.netlify.com/sites/salsa-rs/deploys/67118638fd98680008254f64

@@ -77,11 +81,12 @@ trait Db: salsa::Database {
}

#[salsa::db]
#[derive(Clone)]
Copy link
Contributor

Choose a reason for hiding this comment

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

Nit: I kind of preferred the old salsa's ParallelDatabase trait rather than relying on Clone. It makes the contract more explicit.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It's certainly option, but I'm not sure ParallelDatabase works well with when an end-user of Salsa only has &dyn HirDatabase and it should be safe and reasonable to use Rayon with queries that use &dyn HirDatabase. Like I said in my other comment, I'm going off of this document, but I'd be happy to change this design! I mostly care about making the example work with any database.

Copy link
Member

Choose a reason for hiding this comment

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

This is what I was debating about in those variations-- there might be a hybrid here. That said, I think that ALL databases will effectively be parallel databases under this plan (that is ~required to allow queries to use parallelism internally, since they are written against a dyn Database).

I guess we could still make a ParallelDatabase trait and have them work against a dyn ParallelDatabase, but I'm not convinced there's a use case for "non-parallel databases".

Copy link
Contributor Author

@davidbarsky davidbarsky Aug 27, 2024

Choose a reason for hiding this comment

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

At least in rust-analyzer's case, I can't really think of a situation where it wouldn't make sense to have every Database be a ParallelDatabase. I don't think we'd want to make everything parallel, but having the option to do so without extensive refactors is really valuable, in my view.

@@ -108,6 +108,10 @@ unsafe impl<T: HasStorage> ZalsaDatabase for T {
fn zalsa_local(&self) -> &ZalsaLocal {
&self.storage().zalsa_local
}

fn fork_db(&self) -> Box<dyn Database> {
Copy link
Contributor

Choose a reason for hiding this comment

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

Could we return T instead of a Box<dyn Database>?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Micha: I'm going off the designed specified in the section titled "Clone alternative". Happy to revisit this, if needed!

Copy link
Member

Choose a reason for hiding this comment

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

We can't readily do that because of dyn safety, but there are other ways we can structure it to expose a variation that returns a Self.

Copy link

codspeed-hq bot commented Aug 26, 2024

CodSpeed Performance Report

Merging #568 will not alter performance

Comparing davidbarsky/push-lqummkkxvkzn (0102ffb) with master (710691d)

Summary

✅ 8 untouched benchmarks

src/par_map.rs Outdated
E: Send + Sync,
C: FromParallelIterator<E>,
{
dbg!(db.zalsa().views());
Copy link
Contributor Author

@davidbarsky davidbarsky Aug 26, 2024

Choose a reason for hiding this comment

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

i've been doing a bunch of digging to figure out why this panics when used with tests/parallel/parallel_map.rs test. i initially saw that the underling Zalza::views was empty, so the test would naturally panic—there is nothing to downcast to! I've since added calls to tracked_fn in the test, and now, I'm seeing a downcast-able database:

[src/par_map.rs:16:5] db.zalsa().views() = DynDowncasts {
    vec: [
        DynDowncast(
            "dyn parallel_map::common::LogDatabase",
        ),
    ],

This makes sense! databases are discovered upon first use, but for par_map to work, I think the list of databases to cast to need to be reflexive: that is, they need to include themselves. I'll try making this change.

Copy link
Member

Choose a reason for hiding this comment

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

Ah, yeah, that's easy enough to fix. I was wondering if we'd encounter an issue where the correct view wasn't registered but I think we can fix that too if needed easily enough.

src/par_map.rs Outdated
E: Send + Sync,
C: FromParallelIterator<E>,
{
dbg!(db.zalsa().views());
Copy link
Member

Choose a reason for hiding this comment

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

Ah, yeah, that's easy enough to fix. I was wondering if we'd encounter an issue where the correct view wasn't registered but I think we can fix that too if needed easily enough.

@@ -108,6 +108,10 @@ unsafe impl<T: HasStorage> ZalsaDatabase for T {
fn zalsa_local(&self) -> &ZalsaLocal {
&self.storage().zalsa_local
}

fn fork_db(&self) -> Box<dyn Database> {
Copy link
Member

Choose a reason for hiding this comment

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

We can't readily do that because of dyn safety, but there are other ways we can structure it to expose a variation that returns a Self.

src/table.rs Outdated Show resolved Hide resolved
src/par_map.rs Show resolved Hide resolved
@davidbarsky davidbarsky force-pushed the davidbarsky/push-lqummkkxvkzn branch 2 times, most recently from cbd7159 to acd5acf Compare August 29, 2024 17:55
@davidbarsky davidbarsky marked this pull request as ready for review August 29, 2024 20:18
@davidbarsky
Copy link
Contributor Author

The Miri errors appear to be coming from crossbeam-epoch, but I'm not sure how bad of an error that is.

@Veykril
Copy link
Contributor

Veykril commented Aug 30, 2024

The Miri errors appear to be coming from crossbeam-epoch, but I'm not sure how bad of an error that is.

Judging from the issue tracker that crate seems to have a couple stacked borrows violations

@nikomatsakis
Copy link
Member

Does miri have a way to add 'known failures'...

@nikomatsakis
Copy link
Member

@davidbarsky I'd be ok moving the miri tests to "warn only" for the time being and then trying to investigate the use of crossbeam-epoch more closely.

@davidbarsky
Copy link
Contributor Author

@davidbarsky I'd be ok moving the miri tests to "warn only" for the time being and then trying to investigate the use of crossbeam-epoch more closely.

Lemme see about doing that. I think I still need to port over a test or two over as well.

@davidbarsky
Copy link
Contributor Author

Added a cancellation test.

@davidbarsky davidbarsky force-pushed the davidbarsky/push-lqummkkxvkzn branch 2 times, most recently from a56731f to 132ce16 Compare October 15, 2024 14:42
@MichaReiser
Copy link
Contributor

@davidbarsky what's the status of this PR? We now have a use case where the hacky hand rolled concurrency no longer works 😆

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