Use unsafeDupablePerformIO where possible

unsafeDupablePerformIO is much faster than unsafePerformIO and can be
used safely as long as the underlying operation is pure and we're fine
risking duplicating it in a multi-core scenario. unsafeDupablePerformIO
helps performance a lot on short string where the overhead of
unsafePerformIO dominates.

Closes #41.