【发布时间】:2011-06-14 09:48:32
【问题描述】:
有代码读取 IORef 并根据一些条件和计算创建一个新值。现在它将新值写入该 IORef。但它有可能根本没有改变。新值可能与旧值相同。
在写入IORef之前是否检查值是否不同,或者直接写入IORef,有什么注意事项?
writeIORef在设置前是否检查值是否改变?
通过先检查,是否可以避免写入并节省一点性能?
【问题讨论】:
有代码读取 IORef 并根据一些条件和计算创建一个新值。现在它将新值写入该 IORef。但它有可能根本没有改变。新值可能与旧值相同。
在写入IORef之前是否检查值是否不同,或者直接写入IORef,有什么注意事项?
writeIORef在设置前是否检查值是否改变?
通过先检查,是否可以避免写入并节省一点性能?
【问题讨论】:
writeIORef在设置前是否检查值是否改变?
没有。 writeIORef 包裹writeSTRef,定义为
-- |Write a new value into an 'STRef'
writeSTRef :: STRef s a -> a -> ST s ()
writeSTRef (STRef var#) val = ST $ \s1# ->
case writeMutVar# var# val s1# of { s2# ->
(# s2#, () #) }
通过先检查,您是否可以避免写入并节省一点性能?
在写入IORef之前是否检查值是否不同,或者直接写入IORef,有什么注意事项?
这真的取决于所讨论的算法。你想优化什么?读写的频率/比率是多少?你存储什么样的数据?它是如何包装的?对相关数据进行等式比较的成本是多少?
在确定是否要就地破坏性更新单元格时,需要考虑很多因素:一些特定于算法,一些取决于缓存位置,其他一些取决于代码的结构和形式GHC 生成。因此,回答您的问题非常困难。
引自唐纳德·高德纳的一句话:
我们应该忘记小的效率,比如大约 97% 的时间:过早的优化是万恶之源
除非您正处于试图从一些易于理解的实现中找出每一个性能的阶段,否则您最好选择这样的路径
然后继续。如果您处于想要调整程序的阶段,我建议您学习阅读GHC's human-readable generated output (Core),因为这样您就可以做出这些决定(在非常细粒度的级别上)在每个程序的基础上。
【讨论】: