The main point is that the big O notation ignores the cache misses.
For example:
- try writing a quicksort as a template to avoid the comparison function calls
- in the sorting loop, switch to an insertion sort when buckets have <= 32 elements
You will see speed improvements of 2 to 3 times faster than a vanilla implementation of quicksort.
Although this approach is slightly more complex on the abstract level, it's faster because it reduces lots cache misses.