上下文:我正在写一些东西来处理日志数据,其中涉及将几 GB 的数据加载到内存中并交叉检查各种内容,查找数据中的相关性并将结果写入另一个文件。 (这本质上是加载到 Druid.io 集群之前的 cooking /非规范化步骤。)为了性能和代码简单性,我想避免将信息写入数据库——假设在可预见的 future 数据量一次处理可以通过给机器增加内存来处理。
我的问题是尝试在我的代码中显式删除重复字符串是否是个好主意;如果是这样,什么是好的方法。这些日志文件中的许多值都是完全相同的文本片段(粗略估计,文件中总文本值的大约 25% 可能是唯一的)。
由于我们谈论的是 GB 数据,虽然 ram 很便宜并且可以进行交换,但仍然存在限制,如果我不小心,我很可能会碰到它。如果我这样做:
strstore := make(map[string]string)
// do some work that involves slicing and dicing some text, resulting in:
var a = "some string that we figured out that has about a 75% chance of being duplicate"
// note that there are about 10 other such variables that are calculated here, only "a" shown for simplicity
if _, ok := strstore[a]; !ok {
strstore[a] = a
} else {
a = strstore[a]
}
// now do some more stuff with "a" and keep it in a struct which is in
// some map some place
在我看来,这会产生“重用”现有字符串的效果,代价是散列查找和比较。看起来是一个很好的权衡。
但是,如果实际上是新的字符串导致内存碎片化并且有各种无人认领的漏洞,这可能没有多大帮助。
我也可以尝试保留一个大字节数组/slice ,其中包含字符数据和索引,但这会使代码难以编写(尤其是必须弄乱 []byte 和字符串之间的转换,这涉及到它自己的分配),而且我可能只是在真正属于 Go 运行时领域的事情上做得不好。
寻求有关解决此问题的方法的任何建议,或者是否有人在处理此类问题时产生了特别有用的机制来解决此问题。
最佳答案
您可以在此处使用许多有趣的数据结构和算法。这取决于您在统计和处理阶段尝试做什么。
我不确定您的日志的可压缩性如何,但您可以再次根据您的用例预处理数据:https://github.com/alecthomas/mph/blob/master/README.md
看看其中一些数据结构以及背景:
关于string - 内存中字符串去重,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32672911/