1 //  Copyright (c) 2011-present, Facebook, Inc.  All rights reserved.
2 //  This source code is licensed under both the GPLv2 (found in the
3 //  COPYING file in the root directory) and Apache 2.0 License
4 //  (found in the LICENSE.Apache file in the root directory).
5 
6 #include <string>
7 
8 #include "db/db_test_util.h"
9 #include "monitoring/thread_status_util.h"
10 #include "port/stack_trace.h"
11 #include "rocksdb/statistics.h"
12 
13 namespace ROCKSDB_NAMESPACE {
14 
15 class DBStatisticsTest : public DBTestBase {
16  public:
DBStatisticsTest()17   DBStatisticsTest() : DBTestBase("/db_statistics_test") {}
18 };
19 
TEST_F(DBStatisticsTest,CompressionStatsTest)20 TEST_F(DBStatisticsTest, CompressionStatsTest) {
21   CompressionType type;
22 
23   if (Snappy_Supported()) {
24     type = kSnappyCompression;
25     fprintf(stderr, "using snappy\n");
26   } else if (Zlib_Supported()) {
27     type = kZlibCompression;
28     fprintf(stderr, "using zlib\n");
29   } else if (BZip2_Supported()) {
30     type = kBZip2Compression;
31     fprintf(stderr, "using bzip2\n");
32   } else if (LZ4_Supported()) {
33     type = kLZ4Compression;
34     fprintf(stderr, "using lz4\n");
35   } else if (XPRESS_Supported()) {
36     type = kXpressCompression;
37     fprintf(stderr, "using xpress\n");
38   } else if (ZSTD_Supported()) {
39     type = kZSTD;
40     fprintf(stderr, "using ZSTD\n");
41   } else {
42     fprintf(stderr, "skipping test, compression disabled\n");
43     return;
44   }
45 
46   Options options = CurrentOptions();
47   options.compression = type;
48   options.statistics = ROCKSDB_NAMESPACE::CreateDBStatistics();
49   options.statistics->set_stats_level(StatsLevel::kExceptTimeForMutex);
50   DestroyAndReopen(options);
51 
52   int kNumKeysWritten = 100000;
53 
54   // Check that compressions occur and are counted when compression is turned on
55   Random rnd(301);
56   for (int i = 0; i < kNumKeysWritten; ++i) {
57     // compressible string
58     ASSERT_OK(Put(Key(i), RandomString(&rnd, 128) + std::string(128, 'a')));
59   }
60   ASSERT_OK(Flush());
61   ASSERT_GT(options.statistics->getTickerCount(NUMBER_BLOCK_COMPRESSED), 0);
62 
63   for (int i = 0; i < kNumKeysWritten; ++i) {
64     auto r = Get(Key(i));
65   }
66   ASSERT_GT(options.statistics->getTickerCount(NUMBER_BLOCK_DECOMPRESSED), 0);
67 
68   options.compression = kNoCompression;
69   DestroyAndReopen(options);
70   uint64_t currentCompressions =
71             options.statistics->getTickerCount(NUMBER_BLOCK_COMPRESSED);
72   uint64_t currentDecompressions =
73             options.statistics->getTickerCount(NUMBER_BLOCK_DECOMPRESSED);
74 
75   // Check that compressions do not occur when turned off
76   for (int i = 0; i < kNumKeysWritten; ++i) {
77     // compressible string
78     ASSERT_OK(Put(Key(i), RandomString(&rnd, 128) + std::string(128, 'a')));
79   }
80   ASSERT_OK(Flush());
81   ASSERT_EQ(options.statistics->getTickerCount(NUMBER_BLOCK_COMPRESSED)
82             - currentCompressions, 0);
83 
84   for (int i = 0; i < kNumKeysWritten; ++i) {
85     auto r = Get(Key(i));
86   }
87   ASSERT_EQ(options.statistics->getTickerCount(NUMBER_BLOCK_DECOMPRESSED)
88             - currentDecompressions, 0);
89 }
90 
TEST_F(DBStatisticsTest,MutexWaitStatsDisabledByDefault)91 TEST_F(DBStatisticsTest, MutexWaitStatsDisabledByDefault) {
92   Options options = CurrentOptions();
93   options.create_if_missing = true;
94   options.statistics = ROCKSDB_NAMESPACE::CreateDBStatistics();
95   CreateAndReopenWithCF({"pikachu"}, options);
96   const uint64_t kMutexWaitDelay = 100;
97   ThreadStatusUtil::TEST_SetStateDelay(ThreadStatus::STATE_MUTEX_WAIT,
98                                        kMutexWaitDelay);
99   ASSERT_OK(Put("hello", "rocksdb"));
100   ASSERT_EQ(TestGetTickerCount(options, DB_MUTEX_WAIT_MICROS), 0);
101   ThreadStatusUtil::TEST_SetStateDelay(ThreadStatus::STATE_MUTEX_WAIT, 0);
102 }
103 
TEST_F(DBStatisticsTest,MutexWaitStats)104 TEST_F(DBStatisticsTest, MutexWaitStats) {
105   Options options = CurrentOptions();
106   options.create_if_missing = true;
107   options.statistics = ROCKSDB_NAMESPACE::CreateDBStatistics();
108   options.statistics->set_stats_level(StatsLevel::kAll);
109   CreateAndReopenWithCF({"pikachu"}, options);
110   const uint64_t kMutexWaitDelay = 100;
111   ThreadStatusUtil::TEST_SetStateDelay(ThreadStatus::STATE_MUTEX_WAIT,
112                                        kMutexWaitDelay);
113   ASSERT_OK(Put("hello", "rocksdb"));
114   ASSERT_GE(TestGetTickerCount(options, DB_MUTEX_WAIT_MICROS), kMutexWaitDelay);
115   ThreadStatusUtil::TEST_SetStateDelay(ThreadStatus::STATE_MUTEX_WAIT, 0);
116 }
117 
TEST_F(DBStatisticsTest,ResetStats)118 TEST_F(DBStatisticsTest, ResetStats) {
119   Options options = CurrentOptions();
120   options.create_if_missing = true;
121   options.statistics = ROCKSDB_NAMESPACE::CreateDBStatistics();
122   DestroyAndReopen(options);
123   for (int i = 0; i < 2; ++i) {
124     // pick arbitrary ticker and histogram. On first iteration they're zero
125     // because db is unused. On second iteration they're zero due to Reset().
126     ASSERT_EQ(0, TestGetTickerCount(options, NUMBER_KEYS_WRITTEN));
127     HistogramData histogram_data;
128     options.statistics->histogramData(DB_WRITE, &histogram_data);
129     ASSERT_EQ(0.0, histogram_data.max);
130 
131     if (i == 0) {
132       // The Put() makes some of the ticker/histogram stats nonzero until we
133       // Reset().
134       ASSERT_OK(Put("hello", "rocksdb"));
135       ASSERT_EQ(1, TestGetTickerCount(options, NUMBER_KEYS_WRITTEN));
136       options.statistics->histogramData(DB_WRITE, &histogram_data);
137       ASSERT_GT(histogram_data.max, 0.0);
138       options.statistics->Reset();
139     }
140   }
141 }
142 
143 }  // namespace ROCKSDB_NAMESPACE
144 
main(int argc,char ** argv)145 int main(int argc, char** argv) {
146   ROCKSDB_NAMESPACE::port::InstallStackTraceHandler();
147   ::testing::InitGoogleTest(&argc, argv);
148   return RUN_ALL_TESTS();
149 }
150