Depends on how you measure fast. Are you interested in squeezing out milliseconds or just in big O running time?
Insertion's sort O(n^2) may not be as horrible as it may seems with proper implementation.
If you use binary search for finding the the insertion point your comparisons go down to O(log n) and if you move memory
efficiently you can squeeze out quite a bit of performance.
For comparison on my system binary search saves about a second and a half for sorting 40 000 ints.
$ ./engine.exe 40000
binary_insertion_sort()
Swap: 399585418 swaps
Comp: 596083 comparisons
Time: 14.566 sec
insertion_sort()
Swap: 399585418 swaps
Comp: 399625411 comparisons
Time: 16.119 sec
Similarly, moving 100 000 000 ints one to the left takes 0.5790s with a for loop and only 0.2180s with memmove().
Depending on the size of your data set and the architecture you're running it on it may prove perfectly usable, especially online.
Not all O(n^2) algorithms are created equal, even though they are still O(n^2) at the end of the day.