noisy_metrics_recorder.cc 1.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354
  1. // Copyright 2021 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #include "components/optimization_guide/core/noisy_metrics_recorder.h"
  5. #include <cmath>
  6. #include "base/check_op.h"
  7. #include "base/logging.h"
  8. #include "base/rand_util.h"
  9. NoisyMetricsRecorder::NoisyMetricsRecorder() = default;
  10. NoisyMetricsRecorder::~NoisyMetricsRecorder() = default;
  11. uint32_t NoisyMetricsRecorder::GetNoisyMetric(float flip_probability,
  12. uint32_t original_metric,
  13. uint8_t count_bits) {
  14. DCHECK_LE(flip_probability, 1.0f);
  15. DCHECK_GE(flip_probability, 0.0f);
  16. // |original_metric| should fit within least significant |count_bits|.
  17. DCHECK_LE(original_metric, std::pow(2, count_bits) - 1);
  18. uint32_t flipped_value = 0u;
  19. for (size_t idx = 0; idx < count_bits; ++idx) {
  20. uint32_t flipped_bit = 0;
  21. uint32_t bit = original_metric & 0x1;
  22. original_metric = original_metric >> 1;
  23. float first_coin_flip = GetRandBetween0And1();
  24. if (first_coin_flip < flip_probability) {
  25. flipped_bit = GetRandEither0Or1();
  26. } else {
  27. flipped_bit = bit;
  28. }
  29. flipped_value |= (flipped_bit << idx);
  30. }
  31. // The method has iterated through least significant |count_bits| and did that
  32. // many right shifts. At this point, rest of the bits in |original_metric|
  33. // should be 0.
  34. DCHECK_EQ(original_metric, 0u);
  35. DCHECK_EQ(flipped_value >> count_bits, 0u);
  36. return flipped_value;
  37. }
  38. float NoisyMetricsRecorder::GetRandBetween0And1() const {
  39. return base::RandDouble();
  40. }
  41. int NoisyMetricsRecorder::GetRandEither0Or1() const {
  42. return base::RandInt(0, 1);
  43. }