请考虑以下数据模型:
data Artist = Artist Text
data Song = Song Artist Text
data Catalogue = Catalogue (Set Artist) (Set Song)
您可以看到 Artist
s 来自 Song
s 和 Catalogue
. Catalogue
包含从 Song
引用的所有艺术家的列表s,所以 Artist
的值相同从两个地方引用。
假设我们要生成 Catalogue
使用以下函数的多个应用程序的值:
insertSong :: Song -> Catalogue -> Catalogue
insertSong song@(Song artist title) (Catalogue artists songs) =
Catalogue (Set.insert artist artists) (Set.insert song songs)
很明显 Catalogue
将通过引用 Artist
的相同值来填充作为Song
s 引用,因此通过不存储这些值的副本来节省内存。
问题在于,当我尝试通过分别反序列化一组艺术家和一组歌曲来从序列化数据中重新创建目录时,应用程序占用的内存比生成相同值 Catalogue
时要多得多。与 insertSong
.我怀疑这是由于同一个 Artist
之间的关系丢失造成的。 s 来自 Song
s 和 Catalogue
,这就是为什么我得到 Artist
的值的副本占用额外的内存。
我看到的唯一解决方案是首先反序列化一组艺术家,然后反序列化一组歌曲,同时强制替换 Artist
的值。与第一组中的那些。
所以我的问题是:
- 我的怀疑是对的吗?
- 我看到的解决方案会起作用吗?
- 有没有更好的方法来解决这个问题?
最佳答案
- 这听起来很合理。
- 如果操作正确,它应该可以工作。特别是,您必须确保对所有内容都进行热切评估,以避免从 thunk 中引用旧的 Text 值。
- 您可以选择更智能的序列化格式。例如,当您序列化歌曲时,将艺术家的索引存储在艺术家列表中,而不是完整的艺术家名称。然后在反序列化过程中查找它。
请注意,如果您对字符串进行任何类型的计算,共享也会丢失(即,即使 artist1
和 artist2
相同且共享, f artist1
和 f artist2
可能不是)。如果这成为问题,您也可以对数据结构进行类似的更改。
关于pointers - 对相同数据和内存分配的引用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17643878/