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

perf: Speed up performance of queue.clean when called with a limit #2205

Merged
merged 5 commits into from Dec 14, 2021

Conversation

pxpeterxu
Copy link
Contributor

@pxpeterxu pxpeterxu commented Nov 5, 2021

Motivation

I was trying to clean a large queue with millions of entries. Originally, I ran:

import Queue from 'bull';
const queue = new Queue(...);
queue.clean(0, 'completed');

But this blocked Redis from saving any other records with the error message:

BUSY Redis is busy running a script. You can only call SCRIPT KILL or SHUTDOWN NOSAVE

I switched this to something more like:

import Queue from 'bull';
const queue = new Queue(...);

async function run() {
  let count = null;
  while (count == null || count >= 100) {
    count = (await queue.clean(0, 'completed', 100)).length;
  }
}

But each loop of 100 still took a really long time. Digging into the script, regardless of how many we try to delete, we're listing all the keys on every run of .clean()

local jobIds = rcall(command, KEYS[1], 0, -1)

Changes

  • Change the cleanJobsInSet script so that:
    • If we're trying to clean n entries, only fetch n keys at a time
    • (Note that we might have to loop through this if the first n entries don't have all the timestamps we need, but this should generally still be an improvement)
  • Cleanup: make cleanJobsInSet's variables be all named for slightly easier readability

Testing

Tested in production with my queue -- this sped it up a lot! Also ran it on empty queues to make sure that we ended properly

Also added an automated test for some pagination edge cases

Note for reviewers

It's a lot easier to see changes with "Hide whitespace changes" turned on: https://github.com/OptimalBits/bull/pull/2205/files?diff=split&w=1

@pxpeterxu pxpeterxu changed the title Speed up performance of queue.clean when called with a limit perf: Speed up performance of queue.clean when called with a limit Nov 5, 2021
@manast
Copy link
Member

manast commented Nov 8, 2021

@pxpeterxu thanks, looks good to me.

@roggervalf do we need to port this improvement to BullMQ?

@manast manast merged commit c20e469 into OptimalBits:develop Dec 14, 2021
github-actions bot pushed a commit that referenced this pull request Dec 14, 2021
## [4.1.2](v4.1.1...v4.1.2) (2021-12-14)

### Performance Improvements

* speed up performance of queue.clean when called with a limit ([#2205](#2205)) ([c20e469](c20e469))
@manast
Copy link
Member

manast commented Dec 14, 2021

🎉 This PR is included in version 4.1.2 🎉

The release is available on:

Your semantic-release bot 📦🚀

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants