Live data from Hacker News

Hashed sorting is typically faster than hash tables

reiner.org

21–30 of 67 posts

Re: Hashed sorting is typically faster than hash tables

#21
post #5

Interesting article. It’s actually very strange that the dataset needs to be “big” for the O(n log n) algorithm to beat the O(n). Usually you’d expect the big O analysis to be “wrong” for small datasets. I expect that in this case, like in all cases, as the datasets become gallactically large, the O(n) algorithm will start winning again.

No, because radix sort is not a comparison-based sort and is not O(n log n).

Re: Hashed sorting is typically faster than hash tables

#22
post #5

Interesting article. It’s actually very strange that the dataset needs to be “big” for the O(n log n) algorithm to beat the O(n). Usually you’d expect the big O analysis to be “wrong” for small datasets. I expect that in this case, like in all cases, as the datasets become gallactically large, the O(n) algorithm will start winning again.

That is what baffles me. The difference in big O complexity should be more visible with size, but thats where it looses to the "worse" algorithm. I could imagine the hash table wins again beyond a even greater threshold. Like what about 120GB and beyond?

Radix sort is not a comparison-based sort and is not O(n log n).

Re: Hashed sorting is typically faster than hash tables

#23

Though big enough to be worthwhile at scale, it's notable how small, relatively, the difference is from the out-of-box Rust unstable sort to the tuned radix sort. Lukas Bergdoll and Orson Peters did some really important heavy lifting to get this stuff from "If you're an expert you could probably tune a general purpose sort to have these nice properties" to "Rust's general purpose sort has these properties out of the…

I (Orson Peters) am also here if anyone has any questions :)

Re: Hashed sorting is typically faster than hash tables

#24

It's nice that we can write relatively performant code with the batteries included in these languages and no hand tuning. I only wished it was as easy as that to write code that is secure by default.

I would be happy with code that does what I intended it to do by default.

Re: Hashed sorting is typically faster than hash tables

#25
While the main conclusion of the article isn't unexpected to me I am very surprised a well optimized quicksort isn't faster than radix sort. My experience in C is that you can significantly speed-up quick sort by removing function calls and doing insertion sorts on small arrays at the end. I was never able to get radix sort even close to that performance wise. I don't know Rust at all so it would be pointless for me to try to code an optimized quick sort in it. Hopefully the author knows how to optimize quick sort and is not missing on huge gains there.

Just in case someone feels like porting it to Rust, here is a link to a good and simple quick sort implementation that significantly outperforms standard library one: https://www.ucw.cz/libucw/doc/ucw/sort.html

Re: Hashed sorting is typically faster than hash tables

#26
A way to give radix sort a performance boost is to allocate uninitialized blocks of memory for each bucket that are of size n. It exploits the MMU and you don’t have to worry about managing anything related to buckets potentially overwriting. The MMU is doing all the bookkeeping for you and the OS actually allocates memory only on page access.

Re: Hashed sorting is typically faster than hash tables

#27

Earlier quoted context omitted.

That is what baffles me. The difference in big O complexity should be more visible with size, but thats where it looses to the "worse" algorithm. I could imagine the hash table wins again beyond a even greater threshold. Like what about 120GB and beyond?

As others have pointed out, radix sort is O(64N) = O(N) for a fixed key length of uint64s as in this article So it comes down to the cost of hashing, hash misses, and other factors as discussed in the article. I remember learning that radix sort is (almost?) always fastest if you're sorting integers. A related fun question is to analyze hash table performance for strings where you have no bound on string length.

Sorting wins for unbounded strings because it only needs a prefix of each string.

Re: Hashed sorting is typically faster than hash tables

#29

It's nice that we can write relatively performant code with the batteries included in these languages and no hand tuning. I only wished it was as easy as that to write code that is secure by default.

I would be happy with code that does what I intended it to do by default.

Do-What-I-Mean isn't possible. What Rust does give you is Do-What-I-Say which mostly leaves the problem of saying what you mean, a significant task but one that is hopefully what software engineering was training you to be most effective at.

One important trick is ruling out cases where what you said is nonsense. That can't be what you meant so by ruling it out we're helping you fall into the pit of success and Rust does an admirable job of that part.

Unfortunately because of Rice we must also rule out some cases where what you said wasn't nonsense when we do this. Hopefully not too many. It's pretty annoying when this happens, however, it's also logically impossible to always be sure, Rice again - maybe what you wrote was nonsense after all. So I find that acceptable.

Re: Hashed sorting is typically faster than hash tables

#30

Earlier quoted context omitted.

why is it strange? the case where asymptotically better = concretely worse is usually the exception, not the norm.

We expect asymptotically better algorithms to be, well, asymptotically better. Even if they lose out for small N, they should win for larger N - and we typically expect this "larger N" to not be that large - just big enough so that data doesn't fit in any cache or something like that. However, in this particular case, the higher-complexity sorting algorithms gets better than the hash algorithm as N gets larger, even…

As others have likely pointed out by now, radix sort is not O(n log n).

It's O(k * n), where k is constant with respect to the key size.

For 64-bit keys with 1024 buckets, k==8, so it's O(8 * n) = O(n)

Post reply on HN