在JavaScript中排序32位有符号整数数组的最快方法?
看来标准基数排序确实是这个工作流程的王道。如果有人有时间尝试循环展开或其他修改,我将不胜感激。 我有一个特定的用例,我希望用JavaScript实现尽可能快的排序。客户端脚本将访问大型(50000-2mil)、未排序(基本上是随机的)、整数(32位有符号)数组,然后需要对这些数据进行排序和显示 我已经实现了相当快的就地基数排序和就地快速排序,但是对于我的上限数组长度,它们仍然相当慢。快速排序在数组大小上限上的性能更好,而基数排序在数组大小下限上的性能更好在JavaScript中排序32位有符号整数数组的最快方法?,javascript,performance,algorithm,optimization,sorting,Javascript,Performance,Algorithm,Optimization,Sorting,看来标准基数排序确实是这个工作流程的王道。如果有人有时间尝试循环展开或其他修改,我将不胜感激。 我有一个特定的用例,我希望用JavaScript实现尽可能快的排序。客户端脚本将访问大型(50000-2mil)、未排序(基本上是随机的)、整数(32位有符号)数组,然后需要对这些数据进行排序和显示 我已经实现了相当快的就地基数排序和就地快速排序,但是对于我的上限数组长度,它们仍然相当慢。快速排序在数组大小上限上的性能更好,而基数排序在数组大小下限上的性能更好 Intel i7 870, 4GB, F
Intel i7 870, 4GB, FireFox 8.0
2mil
radixSort(intArr): 172 ms
radixSortIP(intArr): 1738 ms
quickSortIP(arr): 661 ms
200k
radixSort(intArr): 18 ms
radixSortIP(intArr): 26 ms
quickSortIP(arr): 58 ms
问题
- 是否有更好的排序算法实现来满足我的用例/需求
- 是否可以对我的就地基数/快速排序实现进行任何优化以提高性能
- 有没有一种有效的方法将我的就地基数排序从递归函数转换为迭代函数?内存和执行速度
目标
- 我希望这些答案能帮助我在基准测试中获得20-30%的性能提升
澄清/说明
- “DEFINE FAST”我更喜欢在所有现代浏览器上运行良好的一般情况,但是如果有一个特定于浏览器的优化,可以做出显著的改进,这可能是可以接受的
- 排序可以在服务器端完成,但我更愿意避免这种情况,因为JS应用程序可能会成为一个独立的应用程序(与一些现成的专有应用程序配合使用,这些应用程序将传感器数据流式传输到一个文件中)
- JavaScript可能不是实现这一点的最佳语言,但这是一项要求
- 我已经问过这个问题了,一个不正确的答案被投了赞成票,问题结束了
- 我尝试使用多个浏览器窗口实例作为临时多线程;结果没有成功。我想了解有关生成多个并发窗口的有用信息
编辑:我看到您已经在为较小的子阵列使用插入排序。我错过了 使用快速排序的好的现实方法是检查子数组的大小,如果子数组足够短,则使用快速低开销排序,该排序对于较大的数组来说太慢,例如插入排序 伪代码大致如下:
IE 10+ | FF 4+ | Chrome 7+ | Safari 5.1+ | Opera 11.6+
快速排序(数组、开始、结束):
如果((结束-开始)<阈值){
插入\排序(数组、开始、结束);
返回;
}
//这里的常规快速排序
// ...
要确定阈值,您需要在您关心的平台上计时,在您的情况下,可能是在不同的浏览器上。测量具有不同阈值的随机阵列的时间,以找到接近最佳阈值的阵列。如果发现显著差异,您还可以为不同的浏览器选择不同的阈值
现在,如果您的输入不是真正随机的(这是很常见的),您可以看到更好的轴选择是否可以提高性能。一种常用的方法是。您是否考虑过组合算法以最大限度地利用缓存?我在基准测试中看到,当子阵列变小时,您将切换到插入排序。一个有趣的方法是切换到heapsort。与快速排序结合使用,它可以将最坏情况降为O(nlog(n)),而不是O(n^2)。看看。我修改了您的基准测试,并添加了自己的排序功能。 它的性能与radixsort相同,但它的思想(和实现)更简单,它类似于radixsort,但是二进制的,所以您只有两个bucket,可以就地执行。 看 我将代码放在“原地快速排序”的位置(因为它与快速排序非常相似,只是选择了另一种方式的pivot)。
运行它们几次,在我的Chrome 15中,它们的性能非常接近,以至于无法区分它们。我不会对您的排序算法发表评论。你知道的比我多 但是一个好主意是使用网络工作者。这允许排序在后台自己的线程中运行,因此不会阻塞接口。不管怎样,这都是一个很好的练习。Chrome和Firefox都很好地支持它。Opera有一个非线程版本。不确定IE中的支持,但解决这个问题很容易。当然,使用多个线程会带来开销
合并排序可以很容易地制作成多线程版本,这将给您一些性能提升。当然,消息传递会带来时间上的损失,因此,如果它运行得更快,这将取决于您的具体情况。但是请记住,非阻塞特性可能会让最终用户感觉应用程序运行得更快。很有趣的是,基数排序比快速排序慢。你确定你正确地实现了它吗?创建数组花费了多少时间?您是否检查过使用浮点数填充数组的性能是否有所提高
test[x]=parseFloat(…rand..)
在分区中使用三个中位数可能会使QuickSort实现的速度提高10%,并且可以避免QuickSort在偏序子集中遇到的大多数问题。更好的是,中位数为5,这样可以避免三个杀手的中位数,这并不罕见。也许可以创建一个页面来反映尝试过的解决方案?只有我的2美分。。。对于大多数现代处理器而言,片上CPU缓存中可能会有20万个4字节的项目,而200万个可能不会。一旦我们不得不使用DRAM,基数排序的随机访问特性将影响性能。快速排序通常需要顺序内存访问
defaultSort is the built-in JavaScript array.sort with an integer compare function
Intel C2Q 9650, 4GB, FireFox 3.6
2mil
radixSortIP(intArr): 5554 ms
quickSortIP(arr): 1796 ms
200k
radixSortIP(intArr): 139 ms
quickSortIP(arr): 190 ms
defaultSort(intArr): 354 ms
Intel i7 870, 4GB, FireFox 8.0
2mil
radixSortIP(intArr): 990 ms
quickSortIP(arr): 882 ms
defaultSort(intArr): 3632 ms
200k
radixSortIP(intArr): 28 ms
quickSortIP(arr): 68 ms
defaultSort(intArr): 306 ms
QSIP_TYPED | RDXIP_TYPED | QSIP_STD | RDXIP_STD
----------------------------------------------------------
Chrome | 300 1000 600 1300
Firefox | 550 1500 800 1600
IE 10+ | FF 4+ | Chrome 7+ | Safari 5.1+ | Opera 11.6+
quicksort(array, start, end):
if ( (end-start) < THRESHOLD ) {
insertion_sort(array, start, end);
return;
}
// regular quicksort here
// ...