是否存在(低级)GHC功能,允许在IORef
中对特定构造函数/记录字段进行就地更新,以提高效率?
给定以下代码:
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将读出非常大的对象,执行琐碎的修改,并将其写回来。
理论上,只对字段进行就地更新就足够了,而且效率要高得多。
是否有任何GHC功能,例如低级原语,这将允许我为任何ADT这样做?
我知道特殊情况的解决方案是使他们的字段IORef
s而不是结构,但我正在寻找一种方法来实现这对任何结构,包括从库。
没有这样的功能。一般来说,它也不安全:就地修改大对象意味着之前从引用中读取的任何人现在都将获得与以前不同的值。(当然,在安全的情况下可能会有限制。但我敢打赌,情况比你想象的要少。
您可能也有兴趣阅读或注册更新此语言提案。
这在目前是不可能的(GHC 8.10.3)。
好在Haskell中的大多数东西都是作为引用保存的,所以lotsOfData
根本不会被复制(指针会被复制,但8个字节应该是可以承受的)。因此,你的代码应该是高性能的。
我会重构Object
甚至VeryLargeDataType
以包含IORefs,但只有在绝对必要的情况下,即只有在我用尽所有其他优化选项之后。
但是-当然-这只有在你可以控制该类型的情况下才有可能,而且它不是来自库。
好消息是,在Haskell中每天使用的数据结构通常是合理的性能。(一个著名的例子当然是列表。)包通常会记录其功能的复杂性,因此您可以提前计划。