-
Notifications
You must be signed in to change notification settings - Fork 57
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
Optimize baseline and special case performance for kSmallest #37
Conversation
@@ -287,13 +287,22 @@ FastPriorityQueue.prototype.forEach = function(callback) { | |||
FastPriorityQueue.prototype.kSmallest = function(k) { | |||
if (this.size == 0) return []; | |||
k = Math.min(this.size, k); | |||
var fpq = new FastPriorityQueue(this.compare); | |||
const newSize = Math.min((k > 0 ? Math.pow(2, k - 1) : 0) + 1, this.size); | |||
const newSize = Math.min(this.size, (1 << (k - 1)) + 1); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We had a guard against k == 0 which this PR drops. When k = 0, we get (1<<(-1))+1 which is a silly value.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If we guard against k == 0 previously, then this code will look safer (k==1 is fine, k < 1 is not).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Updated with the guard you suggested below.
FastPriorityQueue.js
Outdated
@@ -287,13 +287,22 @@ FastPriorityQueue.prototype.forEach = function(callback) { | |||
FastPriorityQueue.prototype.kSmallest = function(k) { | |||
if (this.size == 0) return []; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if (this.size == 0) return []; | |
if ((this.size == 0) || (k<=0)) return []; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I implemented this change after testing. Similar checks I had tested at this point degraded performance, but this did not.
FastPriorityQueue.js
Outdated
const newSize = Math.min((k > 0 ? Math.pow(2, k - 1) : 0) + 1, this.size); | ||
const newSize = Math.min(this.size, (1 << (k - 1)) + 1); | ||
if (newSize < 2) { | ||
if (newSize < 1) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If you add the guard above, then newSize cannot be zero because this.size>0, and (1<<(k-1)+1) is at least 2. So this branch would not be needed.
You could just say if(newSize == 1) { return [this.peek()]; }
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I found newSize == 1
appeared to reduce performance, so I went with newSize < 2
. This will be safe because this.size
and (1 << (k - 1)) + 1
are both guaranteed to be >= 1
when this is checked (excepting cases that were also previously unsupported).
FastPriorityQueue.js
Outdated
return [this.peek()]; | ||
} | ||
} | ||
if (k < 1) return []; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If you guard at the start for this, as I suggest, then this line is unneeded.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
k < 1
check removed.
@Barbarrosa This is very good. Please consider my comments. |
@lemire I updated the branch based on your comments. Here is the updated performance based on my testing today. Before (slow)
Original PR (faster)
PR after changes (similar to Original PR)
|
Great. Merging. |
@staltz I identified the issue, it's an overflow when requesting larger numbers of records. I'll open a PR to fix it. |
Improve the baseline and special case performance of
kSmallest
.Before:
After: