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

listNetworks optimization #9096

Closed
wants to merge 1 commit into from
Closed

Conversation

abh1sar
Copy link
Collaborator

@abh1sar abh1sar commented May 21, 2024

Description

This PR fixes the performance issue where listNetworks api goes through all the rows of the networks table and takes longer irrespective of the pagination used.

[Draft PR. Needs discussion around how the count of networks is displayed.]

Types of changes

  • Breaking change (fix or feature that would cause existing functionality to change)
  • New feature (non-breaking change which adds functionality)
  • Bug fix (non-breaking change which fixes an issue)
  • Enhancement (improves an existing feature and functionality)
  • Cleanup (Code refactoring and cleanup, that may add test cases)
  • build/CI

Feature/Enhancement Scale or Bug Severity

Feature/Enhancement Scale

  • Major
  • Minor

Bug Severity

  • BLOCKER
  • Critical
  • Major
  • Minor
  • Trivial

Screenshots (if appropriate):

How Has This Been Tested?

How did you try to break this feature and the system with this change?

Copy link
Member

@rohityadavcloud rohityadavcloud left a comment

Choose a reason for hiding this comment

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

LGTM, currently the listNetworks causes fetching all DB rows and applying manual pagination later; this solves for that issue.

Copy link

codecov bot commented May 21, 2024

Codecov Report

All modified and coverable lines are covered by tests ✅

Project coverage is 4.31%. Comparing base (ea9a0f4) to head (96f5736).
Report is 1 commits behind head on 4.19.

Additional details and impacted files
@@             Coverage Diff              @@
##               4.19   #9096       +/-   ##
============================================
- Coverage     14.96%   4.31%   -10.65%     
============================================
  Files          5373     363     -5010     
  Lines        469024   29180   -439844     
  Branches      58818    5091    -53727     
============================================
- Hits          70197    1260    -68937     
+ Misses       391056   27778   -363278     
+ Partials       7771     142     -7629     
Flag Coverage Δ
uitests 4.31% <ø> (ø)
unittests ?

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

@@ -2267,7 +2267,7 @@ public Pair<List<? extends Network>, Integer> searchForNetworks(ListNetworksCmd
isRecursive = true;
}

Filter searchFilter = new Filter(NetworkVO.class, "id", false, null, null);
Filter searchFilter = new Filter(NetworkVO.class, "id", false, cmd.getStartIndex(), cmd.getPageSizeVal());
Copy link
Member

@weizhouapache weizhouapache May 21, 2024

Choose a reason for hiding this comment

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

if networkfilter is Account, Domain or Shared, it should work

However, if the networkfilter is All or AccountDomain, it might not work if the searchFilter is the same
for example, there are 25 networks for account, 25 networks for domain. if networkfilter is All or AccountDomain, and the page size is 20,

  • on first page, it returns 20 networks for account, it is good
  • on second page, it should return the last 5 networks for account, and the first 15 networks for domain. But it will return the last 5 networks for account, and the last 5 networks for domain. right ?
    I think the searchFilter needs to be updated after the each search.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

That's a very good point.
The issue here is that we are concatenating results from multiple queries ( lest's say Q1, Q2, Q3). Things kind of work for the first page. We can adjust pageSize of a query depending on how many results are already returned for other queries.

But if we want to display the second page, it is hard to say which startIndex should be used for Q2. As it depends on how many results were displayed for Q2 on page 1. Which in turn depends on how many Q1 results were there on Page 1. For example, if page 1 had 15 results for Q1 and 5 results for Q2, then page2 Q2 startIndex should be 6.

So, to fix this I think the filter should always have startIndex as 0 and pageSize should be cmd.getPageSizeVal() * (cmd.getStartIndex() + 1)

Filter searchFilter = new Filter(NetworkVO.class, "id", false, 0, (cmd.getStartIndex() + 1) * cmd.getPageSizeVal());

This way we have info on all previous page results and when pagination is applied at the end of the method, the correct result will be returned.

We are losing some optimization if startIndex is higher but it is still better than reading all rows.

Copy link
Member

Choose a reason for hiding this comment

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

Are there not any other API similar to this where pagination is applied where the pattern can be repeated, maybe templates, volumes, offerings?

aclType, true, restartRequired, specifyIpRanges, vpcId, tags, display, vlanId, associatedNetworkId), searchFilter, permittedAccounts);
addNetworksToReturnIfNotExist(networksToReturn, sharedNetworks);
addNetworksToReturnIfNotExist(networksToReturn, sharedNetworks.first());
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

The total count of result won't be super accurate now.
As before we would have gone through all the account specific and domain level networks and gotten the union with sharedNetworks. That would have returned the exact total networks count.

But now we will be working with at max 20 account and domain level networks in the list. So there is no way to apply union with all the shared networks.

For example,
Domain level netowrks = 100
Shared networks = 100
Intersection(Domain, Shared) among all of the domain and shared networks = 50

Before this change :
Total network count = Domain n/w + shared n/w - intersection = 150

After this change:
Intersection(Domain, shared) among the first 20 domain and shared networks returned by the query = 10
Total network count = Domain n/w + shared n/w - intersection = 190

Copy link
Member

Choose a reason for hiding this comment

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

This needs to be accurate too. Perhaps once the query returns the page, we can call a dao::getCount() passing only the list of IDs?

@shwstppr
Copy link
Contributor

@blueorangutan package

@blueorangutan
Copy link

@shwstppr a [SL] Jenkins job has been kicked to build packages. It will be bundled with KVM, XenServer and VMware SystemVM templates. I'll keep you posted as I make progress.

@blueorangutan
Copy link

Packaging result [SF]: ✔️ el7 ✔️ el8 ✔️ el9 ✔️ debian ✔️ suse15. SL-JID 9669

@shwstppr
Copy link
Contributor

Discussed with @abh1sar. It will be worth investigating if instead of querying networks multiple times for different filters.
Worst case, we can use startIndex=0, pageSize=pageNumber*page for initial network queries
I'll also investigate if we can optimize listing for supported services, canusedeploy params.

@rohityadavcloud
Copy link
Member

any update/progress on this @shwstppr ?

@abh1sar
Copy link
Collaborator Author

abh1sar commented Jun 4, 2024

any update/progress on this @shwstppr ?

@rohityadavcloud,
Abhishek suggested to see if there is any alternative way to query the networks only once using some kind of Join instead of querying multiple times. But I didn't get time to look at it yet.

@shwstppr
Copy link
Contributor

shwstppr commented Jun 6, 2024

@rohityadavcloud @abh1sar cc @weizhouapache I created a draft here #9184 to refactor the code to retrieve networks from DB only once. I'm yet to test its efficacy for different parameters but if it works it should allow listing networks with a single DB query

@abh1sar abh1sar closed this Jun 12, 2024
@rohityadavcloud rohityadavcloud removed this from the 4.19.1.0 milestone Jun 12, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

5 participants