unix icon indicating copy to clipboard operation
unix copied to clipboard

Use unsafeDupablePerformIO instead of unsafePerformIO in struct field reads?

Open l29ah opened this issue 3 years ago • 4 comments

As it unsafePerformIO is much slower and forces the program to run single-threadedly while providing no benefits.

l29ah avatar Aug 26 '20 10:08 l29ah

Can you point at a few salient examples?

hs-viktor avatar Apr 11 '22 22:04 hs-viktor

As it unsafePerformIO is much slower and forces the program to run single-threadedly while providing no benefits.

It does provide benefits. bracketed functions inside unsafeDupablePerformIO are broken: https://hackage.haskell.org/package/base-4.16.2.0/docs/System-IO-Unsafe.html#v:unsafeDupablePerformIO

So we'd need to know exactly what you mean to judge whether that's a good idea.

hasufell avatar Jul 10 '22 21:07 hasufell

https://github.com/haskell/unix/blob/b315336f219c9afdf1586bb21c90ee76f59271d1/System/Posix/Files/Common.hsc all of these for example

l29ah avatar Jul 10 '22 22:07 l29ah

Indeed those particular examples are IIRC safe for unsafeDupablePerformIO or even something more aggressive, like similar read-only code in bytestring via accursedUnutterablePerformIO:

{-# INLINE accursedUnutterablePerformIO #-}
accursedUnutterablePerformIO :: IO a -> a
accursedUnutterablePerformIO (IO m) = case m realWorld# of (# _, r #) -> r

The difference with unsafeDupablePerformIO is:

unsafeDupablePerformIO (IO m) = case runRW# m of (# _, a #) -> lazy a

Which takes a few extra precautions against some compiler optimisations, but ultimately (late) inlines to similar code. My sense is that if the bytestring code can read foreign pointer payloads with accursedUnutterablePerformIO, the same should be true here. For example in ByteString.head, we have: accursedUnutterablePerformIO $ unsafeWithForeignPtr x $ \p -> peek p. Which by the way also uses unsafeWithForeignPtr.

hs-viktor avatar Jul 14 '22 04:07 hs-viktor