对数间隔快照
| ← Back to the algorithm list | Published on November 12th, 2022 |
| ← 返回算法列表 | 发布于 2022 年 11 月 12 日 |
When making a series of updates to something, you may wish to also retain a series of snapshots in between updates. For example, you may want to track version history for edits to a document. With limited storage space available, you cannot have a snapshot between every update. You would prefer to have a higher density of recent snapshots and a lower density of long-ago snapshots because it's typically more important to have higher granularity for more recent snapshots.
在对某事物进行一系列更新时,你可能还希望保留更新之间的快照序列。例如,你可能希望跟踪文档编辑的版本历史。由于可用存储空间有限,你无法在每次更新之间都保留一个快照。你更希望最近快照的密度较高,而久远快照的密度较低,因为通常对更近的快照拥有更高的粒度更为重要。
This algorithm is a simple way to keep a set of snapshots logarithmically-spaced back in history. It only ever keeps around roughly 2 log2(n) snapshots for n updates, doesn't require any complex bookkeeping, and runs in O(1) time per update step.
该算法是一种简单的方法,用于在历史记录中以对数间隔保留一组快照。对于 n 次更新,它始终只保留大约 2 log2(n) 个快照,不需要任何复杂的簿记,并且每次更新步骤的运行时间为 O(1)。
The algorithm: After each step, add a new snapshot number n and delete the existing snapshot number n - (firstZeroBit(n) << d) where firstZeroBit(x) returns the value of the least significant zero bit of x. The value d is a customizable shift that determines the density of snapshots. It can be set to any positive integer but has been set to 2 for the visualization below. Here is a possible implementation of firstZeroBit:
算法: 每一步之后,新增一个快照编号 n,并删除已有快照编号 n - (firstZeroBit(n) << d),其中 firstZeroBit(x) 返回 x 最低位零位对应的值。参数 d 是可自定义的位移,决定快照密度,可设为任意正整数,但在下方可视化中设为 2。以下是 firstZeroBit 的一种可能实现:
function
function
firstZeroBit(x) {
firstZeroBit(x) {
let
let
bit = 1
bit = 1
while
while
(bit && (x & bit) !==
(bit && (x & bit) !==
0
0
) bit <<=
) bit <<=
1
1
return
return
bit }
bit }
Here's a second possible (although less understandable) implementation of firstZeroBit that uses bit tricks and is equivalent to the first:
这是 firstZeroBit 的第二种可能实现(虽然可读性较差),它使用位技巧,与第一种实现等价:
function
function
firstZeroBit(x) {
firstZeroBit(x) {
return
r...