在Git Repo中逐步节省Clojure数据结构

时间:2012-12-09 08:34:59

标签: git clojure

注意:

这是有目的地标记Clojure和Git,因为我很乐意在软件的Clojure和Git方面进行重新设计以使事情有效。

问题:

我有一堆clojure数据结构。当写入磁盘时,它们的平均值大约为100 kb(使用pr)。我有大约1000个这样的文件。这些文件是“结构化”文档 - 将它们视为与SVG等效。

现在,我正在对每个文件进行大量小更新(添加/删除节点,更改节点上的属性)。 (然后我(写(pr ...))这些文件。

最后,我将所有这些文件存储在我的git repo中。

问题:

我想知道是否有一种有效的方法来存储这些文件(因为不同的写入只有很小的修改) - 即如果我在内存中有两个单个文档的副本,那么它将是1MB + epsilon,而不是2MB(因为这两个文档只有轻微的差异,并且共享大部分结构。)

我想以某种方式利用这个事实,当它被存储到git中时,可以利用这种相似性。

可能考虑的解决方案:

1)在clojure方面,不要写出整个文件,而只写一个“diff [包含assoc,dissoc]”。 < - 这需要大量的工程设计。

2)在FS端,不是存储单个文件,而是将整个目录放入bzip,然后将其作为单个* .bz2提交(因此,类似的文件将类似于块)。另一方面,git中的* .bz2文件似乎不是一个坏主意。

2 个答案:

答案 0 :(得分:3)

您是否考虑过使用Datomic而不是Git?

你在做什么听起来像是Datomic的一个大致理想的用例,它本质上是一个Clojure风格的“事实图”数据库 - 这正是你的结构化数据所喜欢的。

Datomic以与Clojure不可变数据结构非常相似的方式存储数据,即它使用结构共享来确保小的更改仅需要少量的额外空间。它以类似于git的方式保存整个历史记录 - 甚至还有一个工具可以模拟Datomic中的git repos(codeq

答案 1 :(得分:1)

这是一个有趣的问题。让我们看看我们能做些什么。

在内部,Git会在其数据库中保存您添加到存储库的文件的完整副本。但是,当您运行git gc来优化本地存储库时,Git会将松散的对象打包到packfiles中。使用增量压缩将类似文件存储在packfiles中。引用Pro Git

  

当Git打包对象时,它会查找名称和大小相似的文件,并只保存从一个版本的文件到下一个版本的增量。

因此,优化了Git中类似文件的存储,并减少了空间使用。

让我们从内部转移到用户界面部分。从用户的角度来看,Git基于差异。当您浏览提交时,合并补丁并查看您主要处理差异的更改。 Diffs是面向行的。因此,单行中的最小变化导致行的旧版本和新版本作为整体存储在生成的diff中。我们如何才能使您描述的文件之间的差异更容易阅读?缩短线条。我看到了实现它的两种简单方法。

首先,不是保存Clojure数据结构,而是将它们转换为YAML。具有以YAML格式存储的数据的文件具有相对较短的行,这解决了该问题。 clj-yaml应该派上用场。

如果您坚持将数据存储为s表达式,则第二个想法是用换行符替换生成文件中的所有空格。如果可读性很重要,您可以在之后缩进它们。在应用简单的正则表达式之前,用\n替换每个空格,检查是否有任何包含空格的字符串。