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

Improve query performance for Manage Packages #5573

Merged
merged 5 commits into from
Mar 6, 2018

Conversation

chenriksson
Copy link
Member

@chenriksson chenriksson commented Mar 2, 2018

First optimization for #5461, which covers 2 fixes:

  1. Regression from d8371bd

In UsersController, fix sent to query off the request table instead of the large list of packages. Performance was hard to measure, as it was hanging due to the regression.

  1. Optimize packages query to only sort in DB, based on IsLatest columns

In PackageService, modified the EF query to sort and select based on IsLatest state in DB. Previously we'd read all rows and sort in memory (on NuGetVersion as last resort) to handle cases where IsLatest wasn't set due to concurrency issues.

The second optimization helps mostly in scenarios with many versions, as opposed to many registrations. Results below:

Scenario 1: 59K registrations, 59K versions (NuGetStagingTest on DEV)

  • BEFORE: 48.54, 49.41, 60, 35.74, 49.13 => 45.71s

  • AFTER: 36.12, 49.95, 43.13, 40.32, 46.30 => 41.47 (-9.28%)

Scenario 2: 100 registrations, 52K versions (DEV, various packages)

  • BEFORE: 126, 144, 90, 108, 78 => 100.5s

  • AFTER: 2.71, 3.15, 2.28, 2.23, 2.26 => 2.37s (-97.64%)

// row (descending [Key]) as opposed to reading all rows into memory and sorting on NuGetVersion.
return packages
// order booleans desc so that true (1) comes first
.OrderByDescending(p => p.IsLatestStableSemVer2)
Copy link
Member

Choose a reason for hiding this comment

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

👏

@chenriksson
Copy link
Member Author

@joelverhagen Can you review my last push (663bceb)? I had a bug where I wasn't getting the correct latest version... EF doesn't preserve the ordering done before groupby like linq-to-objects does.

Also added a fix for #5375: .ThenByDescending(p => p.Listed) should order published versions first. UsersController.Packages applies filter .Where(p => p.Listed) which should exclude these from the Published list. (I'm assuming !Listed when PackageState != Available... but correct me if I'm wrong and I can also look at PackageState)

Scenario 2: 100 registrations, 52K versions (re-run morning of 3/5)

  • BEFORE: 72s, 84s, 72s, 84s, 84s => 78s
  • AFTER: 4.6s, 4.64s, 4.52s, 4.55s, 4.48s => 4.54s (-94.18%)

@joelverhagen
Copy link
Member

EF doesn't preserve the ordering done before groupby like linq-to-objects does.

WOW! That's a serious gotcha.

.ThenByDescending(p => p.Listed)

This doesn't seem 100% critical since this is a package owner view, but seems fine.

I'm assuming !Listed when PackageState != Available...

Invalid assumption. You need to filter out non-Available if you actually want that.

@@ -1006,9 +1006,10 @@ public override void ReturnsOnlyLatestStableSemVer2PackageIfBothExist(User curre
public override void ReturnsOnlyLatestStablePackageIfNoLatestStableSemVer2Exist(User currentUser, User packageOwner)
=> base.ReturnsOnlyLatestStablePackageIfNoLatestStableSemVer2Exist(currentUser, packageOwner);

[MemberData(nameof(TestData_RoleVariants))]
[Theory(Skip = "Disabled: FindPackagesByAnyMatchingOwner does not order by NuGetVersion for better performance")]
public override void ReturnsCorrectLatestVersionForMixedSemVer2AndNonSemVer2PackageVersions_IncludeUnlistedTrue(User currentUser, User packageOwner)
Copy link
Contributor

Choose a reason for hiding this comment

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

Can we remove the test? What's the benefit of leaving it here?

Copy link
Contributor

@skofman1 skofman1 left a comment

Choose a reason for hiding this comment

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

:shipit:

var orgSent = currentUser.Organizations
.Where(m => ActionsRequiringPermissions.HandlePackageOwnershipRequest.CheckPermissions(currentUser, m.Organization) == PermissionsCheckResult.Allowed)
.SelectMany(m => _packageOwnerRequestService.GetPackageOwnershipRequests(requestingOwner: m.Organization));
var sent = userReceived.Union(orgReceived);
Copy link
Contributor

Choose a reason for hiding this comment

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

Is this the same as line 374? Should it be
var sent = userSent.Union(orgSent)?

Copy link
Member Author

Choose a reason for hiding this comment

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

Wow, great catch @cristinamanum !

@chenriksson chenriksson force-pushed the chenriks-perf-mypackages branch from c6c7c90 to 0c2b1c9 Compare March 6, 2018 17:27
@chenriksson chenriksson merged commit 512cbd6 into dev Mar 6, 2018
@chenriksson chenriksson deleted the chenriks-perf-mypackages branch March 6, 2018 17:47
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