Upgrade to Pro — share decks privately, control downloads, hide ads and more …

HdrHistogram紹介:ストリーミングで統計値を算出するための 高速・省メモリなライブラリ

HdrHistogram紹介:ストリーミングで統計値を算出するための 高速・省メモリなライブラリ

Takatomo Torigoe

June 16, 2023
Tweet

More Decks by Takatomo Torigoe

Other Decks in Programming

Transcript

  1. ストリーミングの素朴な平均と分散 • 平均は簡単 ◦ 記録:総和・総数を足しこむ ◦ 算出:総和を総数で割る • 分散も公式を使えば簡単……? ◦

    記録:総和・総二乗和・総数を足しこむ ◦ 算出:右式に従って計算 ◦ 大きな数の小さな差を求めるため 計算誤差が大きく、負数が出ることも 分散の意味と2通りの求め方・計算例 https://manabitimes.jp/math/1081
  2. Welford法 • 平均と分散の漸化式を用いる算出方法、精度良く、負数になることがない • Knuth本(Art of Computer Programming)で紹介されているらしい Initialize M1

    = x1 and S1 = 0. For subsequent x‘s, use the recurrence formulas Mk = Mk-1+ (xk – Mk-1)/k Sk = Sk-1 + (xk – Mk-1)*(xk – Mk). For 2 ≤ k ≤ n, the kth estimate of the variance is s2 = Sk/(k – 1). Accurately computing running variance https://www.johndcook.com/blog/standard_deviation/
  3. ストリーミングの素朴なヒストグラム (1) • 固定幅ビンでカウンターを持つ方法 ◦ 例:0~10、10~20、20~30、…… ▪ 上例の精度:±5 ◦ 遅延時間などの場合、だいたい10msec、たまに10secとか、レンジが広い

    ▪ ビン幅が狭いと、値がほとんどない領域のためにメモリを食う ▪ ビン幅が広いと、値が集中している領域の解像度が悪くなる • 90%が10msec以内に収まっているのに、さすがにビンが一つでは……
  4. ストリーミングの素朴なヒストグラム (2) • 指数幅ビンでカウンターを持つ方法 ◦ 例:1~2、2~4、5~8、…… ▪ 上例の精度:70~141% ◦ レンジが広くてもメモリは抑えられる

    ◦ 記録時のビン決定にlog計算を行う必要があるので記録がちょっと重い ▪ logの底が2の場合はビット演算でいいため軽いが、さすがに精度が粗い
  5. HdrHistogram: A High Dynamic Range Histogram • 指数幅の主ビンを、固定幅の幅ビンで分割する、ハイブリッド方式 ◦ 0~255

    (256 bins) ▪ 0~1、1~2、2~3、…… ◦ 256~512 (128 bins) ▪ 256~258、258~260、260~262、…… ◦ 512~1024 (128 bins) ▪ 512~516、516~520、520~524、…… ◦ …… ◦ 上例の精度:±0.4%(有効桁数2)
  6. HdrHistogram実装 int getBucketIndex(final long value) { return leadingZeroCountBase - Long.numberOfLeadingZeros(value

    | subBucketMask); } int getSubBucketIndex(final long value, final int bucketIndex) { return (int)(value >>> (bucketIndex + unitMagnitude)); } • 記録時にカウントアップするビンのインデックス決定が、 高速な足し算・引き算・ビット演算のみで尽きているのがポイント(なはず) https://github.com/HdrHistogram/HdrHistogram/blob/3904a74e1896c22dc8a8afb0b29176a04f ee7a28/src/main/java/org/HdrHistogram/AbstractHistogram.java#L2425
  7. HdrHistogramライブラリ情報 • オリジナルはJava実装 ◦ JavaScript、C、C#、Python、Erlang、Rust、Go、に移植されている • Java実装にはHistogramのバリエーションが色々ある ◦ DoubleHistogram ▪

    記録値の型の違い(デフォルトはlong) ◦ IntCountsHistogram、ShortCountsHistogram ▪ カウンター値の型の違い(デフォルトはlong) ◦ AtomicHistogram、ConcurrentHistogram、SynchronizedHistogram ▪ Javaにおけるマルチスレッドの取り扱いの違い