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

Slow lockfile gen #1261

Merged
merged 7 commits into from
Aug 23, 2024
Merged

Slow lockfile gen #1261

merged 7 commits into from
Aug 23, 2024

Conversation

finnhodgkin
Copy link
Contributor

@finnhodgkin finnhodgkin commented Aug 1, 2024

Description of the change

#1262
Lockfile generation on my large work project takes over 3 minutes.
Adding a bunch of memoisation and combining many individual sqlite queries into one gets this down to 1.5 seconds.

Checklist:

  • Added the change to the "Unreleased" section of the changelog
  • Added some example of the new feature to the README
  • Added a test for the contribution (if applicable)

P.S.: the above checks are not compulsory to get a change merged, so you may skip them. However, taking care of them will result in less work for the maintainers and will be much appreciated 😊

@f-f
Copy link
Member

f-f commented Aug 17, 2024

@finnhodgkin I am interested in merging this, perf is something we care about a lot. You can go ahead with the cleanup and we can get this merged. But I can also review before that if that's something you'd like.

@finnhodgkin
Copy link
Contributor Author

finnhodgkin commented Aug 18, 2024

In my head I was going to clean this up straight after pushing but got distracted. I'll sort it tomorrow.

The thing I could do with a hand on is the sqlite query. I think it's safe to leave un-paramatised because it's called with Array PackageName which is sanitised, but coming from postgres it just feels wrong. Spreading parameters hit the upper limit of params and a single array param just doesn't seem to be possible. Currently:

export const getMetadatasImpl = (db, names) => {
  let query = 'SELECT * FROM package_metadata WHERE name IN (@names)';
  return db.prepare(query).all({ names: names.map((n) => `'${n}'`).join(',') });
};

Was possibly just calling it incorrectly, will test - WiseLibs/better-sqlite3#1109

Went with WiseLibs/better-sqlite3#283 (comment) in the end which seems to work.

@finnhodgkin
Copy link
Contributor Author

@f-f should be good to review now as long as CI goes smoothly.

Copy link
Member

@f-f f-f left a comment

Choose a reason for hiding this comment

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

This is great now 👏

We should adjust a few comments and names, but it's otherwise good to go

src/Spago/Command/Fetch.purs Show resolved Hide resolved
src/Spago/Command/Fetch.purs Outdated Show resolved Hide resolved
src/Spago/Db.js Outdated Show resolved Hide resolved
@@ -62,6 +63,7 @@ type RegistryEnv a = Record (RegistryEnvRow a)
type RegistryFunctions =
{ getManifestFromIndex :: PackageName -> Version -> Spago (LogEnv ()) (Maybe Manifest)
, getMetadata :: PackageName -> Spago (LogEnv ()) (Either String Metadata)
, getMetadatas :: Array PackageName -> Spago (LogEnv ()) (Either String (Map PackageName Metadata))
Copy link
Member

Choose a reason for hiding this comment

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

Is there any point in keeping getMetadata as well now that we have getMetadatas?

As an aside, data is a latin word that's already plural, so adding the s suffix doesn't feel right. How about renaming to getMetadataForPackages?

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 singular version is still used in Command.Repl, Command.Publish and Command.Registry so I just left it alone.

Thanks, will swap to suggested name, had the same thought re datas but wasn't sure about a good replacement.

Copy link
Member

Choose a reason for hiding this comment

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

The singular version is still used in Command.Repl, Command.Publish and Command.Registry so I just left it alone.

Sure, but we can now call the new implementation passing in a singleton array [packageName]? Having two implementations for the same thing guarantees that they will go out of sync in the future, so I'd rather remove the singular version now.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Oh sure. Like 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 could replace the function entirely but it feels useful being able to look up a single package without Map.lookuping the results.

Copy link
Member

Choose a reason for hiding this comment

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

Yeah that makes sense, thanks!

@f-f
Copy link
Member

f-f commented Aug 23, 2024

@finnhodgkin could you merge with latest?

@f-f f-f merged commit 72b2e61 into purescript:master Aug 23, 2024
5 checks passed
@f-f
Copy link
Member

f-f commented Aug 23, 2024

Thank you!

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.

2 participants