作者: 谢瑞阳 10225101483 徐翔宇 10225101535
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

159 lines
3.6 KiB

  1. // Copyright (c) 2012 The LevelDB 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. See the AUTHORS file for names of contributors.
  4. #include "leveldb/filter_policy.h"
  5. #include "util/logging.h"
  6. #include "util/testharness.h"
  7. #include "util/testutil.h"
  8. namespace leveldb {
  9. static const int kVerbose = 1;
  10. static Slice Key(int i, char* buffer) {
  11. memcpy(buffer, &i, sizeof(i));
  12. return Slice(buffer, sizeof(i));
  13. }
  14. class BloomTest {
  15. private:
  16. const FilterPolicy* policy_;
  17. std::string filter_;
  18. std::vector<std::string> keys_;
  19. public:
  20. BloomTest() : policy_(NewBloomFilterPolicy(10)) { }
  21. ~BloomTest() {
  22. delete policy_;
  23. }
  24. void Reset() {
  25. keys_.clear();
  26. filter_.clear();
  27. }
  28. void Add(const Slice& s) {
  29. keys_.push_back(s.ToString());
  30. }
  31. void Build() {
  32. std::vector<Slice> key_slices;
  33. for (size_t i = 0; i < keys_.size(); i++) {
  34. key_slices.push_back(Slice(keys_[i]));
  35. }
  36. filter_.clear();
  37. policy_->CreateFilter(&key_slices[0], key_slices.size(), &filter_);
  38. keys_.clear();
  39. if (kVerbose >= 2) DumpFilter();
  40. }
  41. size_t FilterSize() const {
  42. return filter_.size();
  43. }
  44. void DumpFilter() {
  45. fprintf(stderr, "F(");
  46. for (size_t i = 0; i+1 < filter_.size(); i++) {
  47. const unsigned int c = static_cast<unsigned int>(filter_[i]);
  48. for (int j = 0; j < 8; j++) {
  49. fprintf(stderr, "%c", (c & (1 <<j)) ? '1' : '.');
  50. }
  51. }
  52. fprintf(stderr, ")\n");
  53. }
  54. bool Matches(const Slice& s) {
  55. if (!keys_.empty()) {
  56. Build();
  57. }
  58. return policy_->KeyMayMatch(s, filter_);
  59. }
  60. double FalsePositiveRate() {
  61. char buffer[sizeof(int)];
  62. int result = 0;
  63. for (int i = 0; i < 10000; i++) {
  64. if (Matches(Key(i + 1000000000, buffer))) {
  65. result++;
  66. }
  67. }
  68. return result / 10000.0;
  69. }
  70. };
  71. TEST(BloomTest, EmptyFilter) {
  72. ASSERT_TRUE(! Matches("hello"));
  73. ASSERT_TRUE(! Matches("world"));
  74. }
  75. TEST(BloomTest, Small) {
  76. Add("hello");
  77. Add("world");
  78. ASSERT_TRUE(Matches("hello"));
  79. ASSERT_TRUE(Matches("world"));
  80. ASSERT_TRUE(! Matches("x"));
  81. ASSERT_TRUE(! Matches("foo"));
  82. }
  83. static int NextLength(int length) {
  84. if (length < 10) {
  85. length += 1;
  86. } else if (length < 100) {
  87. length += 10;
  88. } else if (length < 1000) {
  89. length += 100;
  90. } else {
  91. length += 1000;
  92. }
  93. return length;
  94. }
  95. TEST(BloomTest, VaryingLengths) {
  96. char buffer[sizeof(int)];
  97. // Count number of filters that significantly exceed the false positive rate
  98. int mediocre_filters = 0;
  99. int good_filters = 0;
  100. for (int length = 1; length <= 10000; length = NextLength(length)) {
  101. Reset();
  102. for (int i = 0; i < length; i++) {
  103. Add(Key(i, buffer));
  104. }
  105. Build();
  106. ASSERT_LE(FilterSize(), (length * 10 / 8) + 40) << length;
  107. // All added keys must match
  108. for (int i = 0; i < length; i++) {
  109. ASSERT_TRUE(Matches(Key(i, buffer)))
  110. << "Length " << length << "; key " << i;
  111. }
  112. // Check false positive rate
  113. double rate = FalsePositiveRate();
  114. if (kVerbose >= 1) {
  115. fprintf(stderr, "False positives: %5.2f%% @ length = %6d ; bytes = %6d\n",
  116. rate*100.0, length, static_cast<int>(FilterSize()));
  117. }
  118. ASSERT_LE(rate, 0.02); // Must not be over 2%
  119. if (rate > 0.0125) mediocre_filters++; // Allowed, but not too often
  120. else good_filters++;
  121. }
  122. if (kVerbose >= 1) {
  123. fprintf(stderr, "Filters: %d good, %d mediocre\n",
  124. good_filters, mediocre_filters);
  125. }
  126. ASSERT_LE(mediocre_filters, good_filters/5);
  127. }
  128. // Different bits-per-byte
  129. } // namespace leveldb
  130. int main(int argc, char** argv) {
  131. return leveldb::test::RunAllTests();
  132. }