设计思路
基于采样的测量方法只有当测量时间足够长以后才能够提供准确率的保证. 我们把收敛时间定义成为从开始测量到获得准确的测量结果所用的时间.
NitroSketch的关键创新点:
想法一: 保持原有的多哈希表结果, 并且基于哈希表进行采样 (而不是基于信息流进行采样). 当一个数据包到达的时候, 对于每一个哈希表, 我们都以概率 p p p对其进行更新. 通过选取合适的 p p p的值, 我们可以使对每个数据包进行的进行哈希和更新哈希表的次数减少到1以下. 但是这个想法对于每个数据包都需要进行多次取随机数的操作, 而取随机数是一个相当耗时的操作.
想法二: 通过几何采样 (Geometric Sample)来减少取随机数的操作的次数. 为了避免对每一个数据包都取多个随机数, 我们采用对几何分布进行采样的方式来决定(1)下一步更新哪一个哈希表, 以及(2) 在更新哈希表之前需要跳过多少个数据包. 假设采样成功概率为 p p p, 则我们对下一个数据包(即跳过0个数据包)进行采样的概率为 Pr ( X = 0 ) = p \Pr(X=0) = p Pr(X=0)=p, 跳过1个数据包进行采样的概率为 Pr ( X = 1 ) = ( 1 − p ) p \Pr(X=1) = (1-p)p Pr(X=1)=(1−p)p, 依此类推, 跳过 k k k个数据包进行采样的概率为 Pr ( X = k ) = ( 1 − p ) k − 1 p \Pr(X=k) = (1-p)^{k-1}p Pr(X=k)=(1−p)k−1p. 因此, D ( n ) = ∑ k = 0 n Pr ( X = k ) = 1 − ( 1 − p ) n + 1 D(n)=\sum_{k=0}^n\Pr(X=k)=1-(1-p)^{n + 1} D(n)=∑k=0nPr(X=k)=1−(1−p)n+1即为一个几何分布. 因此, 为决定下一次对哪一个数据包进行采样, 我们可以取一个随机数 Y Y Y. 如果 Y ≤ D ( 0 ) Y\le D(0) Y≤D(0), 则我们对下一个数据包进行采样; 否则, 如果 D ( k ) < Y ≤ D ( k + 1 ) D(k) < Y \le D(k+1) D(k)<Y≤D(k+1), 则我们从下一个数据包开始, 跳过 k + 1 k+1 k+1个数据包再进行采样. 假设我们有5个哈希表 H 0 , H 2 , ⋯ , H 4 H_0, H_2, \cdots, H_4 H0,H2,⋯,H4, 当前我们对数据包进行采样并更新哈希表 H 3 H_3 H3. 通过几何采样我们得知, 我们需要跳过5个数据包进行采样, 即我们需要从下一个数据包开始的第6个数据包进行采样, 则我们对这个数据包采样的时候需要更新的哈希表为 H ( 3 + 6 ) % 5 H_{(3+6)\%5} H(3+6)%5即 H 4 H_4 H4. (这部分内容大多是根据我的理解写的, 而非直接抄录原文的内容)
想法三: 根据数据包到达速率调整采样频率来减少收敛时间. 如果我们使用固定的采样频率, 那么我们必须要兼顾到可能的最大的数据包到达速率, 因此不得不选择一个较小的采样频率. 但是当数据包到达速率较小的时候, 一个过小的采样频率会导致收敛时间不必要地增加, 因此根据数据包到达速率动态调整采样频率能够在兼顾CPU负荷的情况下获得更高的准确率和更短的收敛时间.
我们有两种自适应的采样模式. (1) AlwaysLineRate: 将采样频率 p p p设为当前数据包到达频率的倒数, 因此在单位时间内, 我们进行采样的次数是一定的. (2) AlwaysCorrect: 开始的时候采用 p = 1.0 p=1.0 p=1.0的采样频率对数据流进行采样, 但是我们的采样结果能够收敛以后就切换到AlwaysLineRate模式进行采样.
想法四: 把需要更新的数据包和哈希桶缓存起来, 并使用SIMD进行并行操作来提高效率. 这个只是作者采样的一个小技巧, 没有什么值得讨论的.
理论分析
假设 U \mathcal{U} U为所有数据流的集合, 而 f x f_x fx是数据流 x x x的长度 (比如数据包数), 其中 x ∈ U x\in \mathcal{U} x∈U. L k ≜ F k k = ∑ x ∈ U f x k k L_k\triangleq\sqrt[k]{F_k} = \sqrt[k]{\sum_{x\in\mathcal{U}}f_x^k} Lk≜kFk=k∑x∈Ufxk是频数向量 f f f的第 k k k范数 (k-th norm). 特别地, L 1 L_1 L1是被测数据包的总数. 假设我们采用恒定的采样概率 p p p (这里的采样概率是计算几何分布时候的概率, 而不是采样频率)对网络流量进行采样.
定理1. 令 d ≜ log 2 δ − 1 d\triangleq \log_2\delta^{-1} d≜log2δ−1, w ≜ 4 ϵ − 1 w\triangleq 4\epsilon^{-1} w≜4ϵ−1. 对于给定信息流, 如果存在一个足够大的常数 c c c, 有 L 1 ≥ c ⋅ ( ϵ − 2 p − 1 log δ − 1 ) L_1 \ge c\cdot (\epsilon^{-2}p^{-1}\sqrt{\log\delta^{-1}}) L1≥c⋅(ϵ−2p−1logδ−1), 则NitroSketch + Count-Min满足如下不等式:
Pr [ ∣ f x ^ − f x ∣ ≥ ϵ L 1 ] ≤ δ \Pr[|\widehat{f_x} - f_x|\ge \epsilon L_1]\le \delta Pr[∣fx
−fx∣≥ϵL1]≤δ
其中 f x f_x fx和 f x ^ \widehat{f_x} fx
分别是数据流 f f f的真实频率和估计频率.
定理1在原文中没有给出证明; 按照作者的说法, 它的证明过程来自< Constant Time Updates in Hierarchical Heavy Hitters>(SIGCOMM 2017)这篇文章. 如果我之后读完这篇文章, 那将会在此处给出我的研读笔记的链接.
定理2. 令 w = 8 ϵ − 2 p − 1 w=8\epsilon^{-2}p^{-1} w=8ϵ−2p−1, d = O ( l o g δ − 1 ) d=O(log\delta^{-1}) d=O(logδ−1). AlwaysLineRate模式的空间复杂度为 O ( ϵ − 2 p − 1 log δ − 1 ) O(\epsilon^{-2}p^{-1}\log \delta^{-1}) O(ϵ−2p−1logδ−1), 分摊时间复杂度为O(1 + dp), 并且在信息流中, 如果 L 2 ≥ 8 ϵ − 2 p − 1 L_2 \ge 8\epsilon^{-2}p^{-1} L2≥8ϵ−2p−1, 则有 Pr ( ∣ f x − f x ^ ∣ > ϵ L 2 ) ≤ δ \Pr(|f_x - \widehat{f_x}| > \epsilon L_2) \le \delta Pr(∣fx−fx ∣>ϵL2)≤δ.
证明: 假设当一个数据包到达的时候, 我们会为每一个哈希表进行采样. (我理解的原文应该就是这个意思; 如果真是这样, 那就比较有意思了, 因为NitroSketch的一个主要优势就是我们不需要为每一个哈希表对数据包进行采样.) 令 S i ⊆ S S_i\subseteq S Si⊆S为被采样并更新哈希表 H i H_i Hi的数据包的集合, 其中 i = 1 , ⋯ , d i = 1, \cdots, d i=1,⋯,d. 此外, 我们令 f i , x ≜ ∣ { j ∣ ( x j ∈ S i ) ∧ ( x j = x ) } ∣ f_{i, x}\triangleq|\{j | (x_j \in S_i) \wedge(x_j = x)\}| fi,x≜∣{ j∣(xj∈Si)∧(xj=x)