In-place update in IO

Viewed 85

Is there a (low-level) GHC feature which will allow an in-place update of a particular constructor/record field in an IORef, for efficiency?

Given the following code:

data Object = Object {
    field1 :: Int
    field2 :: VeryLargeDataType
    }

main :: IO ()
main = do
    var <- newIORef
    writeIORef var $ Object {
             field1 = 42,
             field2 = lotsOfData
        }
    modifyIORef var (\a -> a { field1 = (field1 a + 1) } )
    ...

GHC will read out the very large object, perform the trivial modification, and write it back.

In theory, an in-place update of just the field would be sufficient, and far more efficient.

Is there any GHC feature, e.g. a low-level primitive, that would allow me to do this for any ADT?

I know the special-case solution is to make ther fields IORefs rather than the structure, but I'm looking for a way to do this with any structure, including from a library.

3 Answers

There is no such feature. It is also not safe in general: modifying that large object in-place means that anybody that read from the reference before will now have a different value than they used to. (There may of course be restricted situations where it is safe. But I would bet it's fewer situations than you're guessing.)

You might also be interested in reading or signing up for updates to this language proposal.

This is not possible at this moment (GHC 8.10.3).

The good thing though is that most things in Haskell are kept as references, so the lotsOfData won't get copied at all (the pointer will be, but 8 bytes should be affordable to copy). Therefore, your code should be performant.

I'd refactor Object or even VeryLargeDataType to contain IORefs, but only if absolutely necessary, i.e. only after I've exhausted all other optimization options.

But - of course - that's only possible of you have control over that type, and it isn't coming from a library for example.

Good news is that the data structures that are in every day use in Haskell are often reasonably performant. (One famous example is the List of course.) Packages often document the complexity of their functions, so you can plan ahead.

Related