-
-
Notifications
You must be signed in to change notification settings - Fork 95
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
Sort is incredibly slow #477
Comments
Have you tried with type checking disabled? > S.create({checkTypes: false, env: []}).sort([1, 4, 10, 8, 9, 10])
[1, 4, 8, 9, 10, 10] I imagine this will make a big difference. |
Note that this comparison is not accurate. I was going to leave it at that, but I wanted to make sure the numbers seemed more reasonable. My tests show that Sanctuary is extremely slow, even without type-checking: const R = require('ramda');
const S = require('sanctuary');
const COUNT = 1e4
const time = (msg, fn) => {
let arr = [1, 4, 10, 8, 9, 10]
const now = new Date();
for (let i = 0; i < COUNT; i++) {
fn(arr)
}
console.log(`${msg}: ${(new Date() - now) / COUNT}`)
}
time('Native', arr => arr.sort())
time('Ramda', arr => R.sort((a, b) => a - b, arr))
time('Sanctuary', arr => S.sort(arr))
const S2 = S.create({checkTypes: false, env: []})
time('Sanctuary w/o type-checking', arr => S2.sort(arr))
Running it with Of course, Ramda is not trying to sort an arbitrary foldable monoid over an arbitrary ordered type. Nor is the native version. They content themselves with plain arrays. Sanctuary does much more. But this performance is scary: a tenth of a millisecond to sort a 6-element list, half of a millisecond with type-checking turned on. Edit: That timing function is wrong, but the results are similar if you change it to: const time = (msg, fn) => {
const now = new Date();
for (let i = 0; i < COUNT; i++) {
fn([1, 4, 10, 8, 9, 10])
}
console.log(`${msg}: ${(new Date() - now) / COUNT}`)
} (obviously, in the native case, we shouldn't be re-sorting the resulting sorted array every time.) |
We can definitely look into improving its performance. One thing that comes to mind is implementing an array-specialised path. Let's get benchmarks sorted first though:
|
The current algorithm is
If the argument to That is |
The above could also be used to implement a stable sort. Then one would have to turn the Foldable into an array where each element is tagged with its original index. The comparison function should then break ties by using the index. That would probably make it a bit slower though. |
Are you interested in submitting a pull request, Simon? |
I'd love to 😄 Are there benchmarks I can run to compare the performance before and after? I've implemented the above approach for List. The implementation can be seen here. I've created a benchmark that measures the overall performance and roughly measures the cost of doing a stable sort vs. doing an unstable sort. With stability, the algorithm is only about 50% slower than I personally think doing a stable sort is worth it. The performance difference isn't that huge and a stable sorts goes well with functional programming. To get a bit extra performance I pull off a trick: I check the first element of the list. If it is a |
Wonderful!
https://github.com/sanctuary-js/sanctuary-type-classes/blob/master/bench/README.md I'm sure @Avaq will be happy to answer questions if it's not clear how to run the benchmarks. |
The text was updated successfully, but these errors were encountered: