来自 数据 2022-06-09 05:30 的文章

云盾_cc如何防御_如何防

云盾_cc如何防御_如何防

优化git的合并机制,4月9日10分钟阅读

编者注:这是Palantir软件工程师关于优化git的合并和重命名检测机制的系列文章中的第三篇。点击阅读第一篇和第二篇文章。

这是关于scaling git合并和重命名检测机制的一系列博客文章中的第三篇。特别是,第一部分还包括一些关于合并机制如何工作的背景信息,我们如何在Palantir使用git,ddos防御额外带宽,以及我为什么一直致力于优化和重写它。本系列第一篇文章的背景信息对于理解这篇文章至关重要。因此,如果您不知道git除了为提交存储哈希之外还为文件存储哈希,或者您不知道合并涉及三方内容合并,或者您不知道为什么合并需要完成两组重命名检测,那么您可能需要先返回并阅读背景信息。如果你已经知道所有这些东西,继续阅读。在这篇文章中,我将考虑另一个优化,一个在第一篇文章中总结的简单的"查找路径,其中检测重命名不会改变结果,并且不检测这些路径的重命名。"损坏的工作最终会得到回报。懒惰现在是有回报的

当面对运行O(N²)算法的代码在大量输入上运行时,并且希望使其更快时,防御cc攻击教学,大多数人可能会问自己以下问题之一:

这里是否可以使用O(N log N)甚至O(N)算法?即使我们不能提高算法的复杂性,我们能否以一种使代码速度提高数倍的方式对代码进行优化?是否可以使用近似的解决方案来解决稍有不同的问题,但为我们提供足够好的解决方案,这样做会更快吗?我们是否可以随着时间的推移以某种方式缓存相关信息,以减少我们需要的计算成本?

您可能会注意到,本系列之前的博文本质上属于近似解决方案类别。然而,我并没有按照发现它们的顺序来讨论这些优化;第一篇博客文章实际上是我的第二次优化,第二篇博客文章是我的第三次优化。我最初的优化并不是因为回答了上面的任何一个问题,而是一组完全不同的问题:

如果我们不进行计算,那会有多糟糕?在某些情况下,我们能逃脱惩罚吗?

实际上,你可能会说,我采用了计算机科学中懒惰评估的概念——在被要求之前不评估结果——并试图通过说"不,你不需要这些;我只是不想计算它们"-并试图找出我什么时候可以侥幸逃脱。

(鹰眼可能认为我以前的优化和当前的优化都是不同形式的"使N变小"。前两次优化是通过寻找替代方法来计算或近似某些重命名来实现的,当前的一个是决定不计算一些重命名。)

为什么我们需要重命名?

合并机制使用重命名有两个目的:

三向内容合并:为了对文件进行三向内容合并,我们需要三个不同的文件版本。如果历史记录的一侧重命名了文件,则该文件的某些内容位于与合并库中不同的路径下。目录重命名检测:当历史记录的一侧重命名目录,而历史记录的另一侧向该目录添加新文件时,我们希望能够提醒用户需要选择这些新文件是保留在旧目录中还是移动到新目录。

如果我们不进行重命名检测,重命名的文件可能会显示为旧文件名的修改/删除冲突,以及新文件名的新文件。两者都将出现在工作副本中,都将进行编辑,合并库中文件的原始版本将不明显,用户将试图协调两者。此外,如果我们不进行重命名检测,防御游戏cc,当这些目录中的所有其他文件都移到其他位置时,放入旧目录中的新文件可能会"落在后面"。

好的,我们需要重命名;但是我们需要所有这些吗?

如果为了三方内容合并或目录重命名检测的目的需要重命名,那么我们需要它。让我们深入研究这两种情况,看看它们中的任何一种是否在所有情况下都需要重命名,或者是否存在可以跳过重命名检测的情况:

三方内容合并

三方内容合并是为了调和历史双方的差异。如果只有历史的一面修改了文件的内容,服务器怎么防御cc攻击,那么我们不需要进行三方内容合并。让我们看看这两种可能性中的每一种,看看为什么会出现这种情况。简要版本为:

如果重命名侧的文件内容未修改⇒ 我们可以进行精确的重命名检测,如果文件内容没有在未命名端被修改,这将非常便宜⇒ 检测到该源文件的重命名与此无关

让我们更详细地了解这两种情况。让我们使用两个文件名,old.c和new.c,以及以下缩写的对象ID(其中值"000000"用于表示该提交中缺少该文件)。第一种情况与此类似:

old.c new.c MERGE_BASE:01d01d 000000 MERGE_SIDE1:000000 01d01d MERGE_SIDE2:5e1ec7 000000

在这里,精确的重命名检测将确定MERGE_BASE中的old.c和MERGE_SIDE1中的new.c是相关的(事实上是相同的)。这意味着我们应该在merge_BASE:old.c、merge_SIDE1:new.c和merge_SIDE2:old.c之间进行三方内容合并。但是,这三个文件中有两个具有相同的内容(注意具有相同的散列),因此甚至不需要三方内容合并;我们已经知道结果将是一个散列为5e1ec7的文件,我们已经将其存储在存储库中。关于重命名的知识让我们知道,5e1ec7是合并结果中名为new.c的文件的散列,而旧的.c应该从结果中删除。

第二种情况更为复杂,可能重命名无关的说法令人惊讶。让我们看看这个案例是什么样子:

old.c new.c MERGE_BASE:01d01d 000000 MERGE_SIDE1:01d01d 000000 MERGE_SIDE2:000000 5e1ec7

因为我声称检测重命名与这个案例无关,让我们比较检测到和未检测到重命名时发生的情况:

如果未检测到重命名⇒

然后,old.c看起来一边没有被修改,另一边被删除,因此应该被删除。new.c看起来像一个新文件,我们应该保持原样。

如果检测到重命名⇒