2 * Copyright 2014 Facebook, Inc.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
21 #include <folly/Benchmark.h>
22 #include <folly/experimental/EliasFanoCoding.h>
23 #include <folly/experimental/test/CodingTestUtils.h>
25 using namespace folly::compression;
27 template <size_t kVersion>
29 static constexpr size_t Version = kVersion;
33 class EliasFanoCodingTest : public ::testing::Test {
36 typedef EliasFanoEncoder<uint32_t, size_t, 0, 0, T::Version> Encoder;
37 typedef EliasFanoReader<Encoder> Reader;
38 testEmpty<Reader, Encoder>();
41 template <size_t kSkipQuantum, size_t kForwardQuantum>
43 typedef EliasFanoEncoder<
44 uint32_t, uint32_t, kSkipQuantum, kForwardQuantum, T::Version> Encoder;
45 typedef EliasFanoReader<Encoder> Reader;
46 testAll<Reader, Encoder>(generateRandomList(100 * 1000, 10 * 1000 * 1000));
47 testAll<Reader, Encoder>(generateSeqList(1, 100000, 100));
51 typedef ::testing::Types<TestType<0>, TestType<1>> TestTypes;
52 TYPED_TEST_CASE(EliasFanoCodingTest, TestTypes);
54 TYPED_TEST(EliasFanoCodingTest, Empty) {
55 TestFixture::doTestEmpty();
58 TYPED_TEST(EliasFanoCodingTest, Simple) {
59 TestFixture::template doTestAll<0, 0>();
62 TYPED_TEST(EliasFanoCodingTest, SkipPointers) {
63 TestFixture::template doTestAll<128, 0>();
66 TYPED_TEST(EliasFanoCodingTest, ForwardPointers) {
67 TestFixture::template doTestAll<0, 128>();
70 TYPED_TEST(EliasFanoCodingTest, SkipForwardPointers) {
71 TestFixture::template doTestAll<128, 128>();
76 constexpr size_t k1M = 1000000;
77 constexpr size_t kVersion = 1;
79 typedef EliasFanoEncoder<uint32_t, uint32_t, 128, 128, kVersion> Encoder;
80 typedef EliasFanoReader<Encoder> Reader;
82 std::vector<uint32_t> data;
83 std::vector<size_t> order;
85 std::vector<uint32_t> encodeSmallData;
86 std::vector<uint32_t> encodeLargeData;
88 typename Encoder::CompressedList list;
93 data = generateRandomList(100 * 1000, 10 * 1000 * 1000, gen);
94 //data = loadList("/home/philipp/pl_test_dump.txt");
95 list = Encoder::encode(data.begin(), data.end());
98 order.reserve(data.size());
99 for (size_t i = 0; i < data.size(); ++i) {
102 std::shuffle(order.begin(), order.end(), gen);
104 encodeSmallData = generateRandomList(10, 100 * 1000, gen);
105 encodeLargeData = generateRandomList(1000 * 1000, 100 * 1000 * 1000, gen);
115 bmNext<bm::Reader>(bm::list, bm::data, bm::k1M);
118 BENCHMARK(Skip1_ForwarQ128_1M) {
119 bmSkip<bm::Reader>(bm::list, bm::data, 1, bm::k1M);
122 BENCHMARK(Skip10_ForwarQ128_1M) {
123 bmSkip<bm::Reader>(bm::list, bm::data, 10, bm::k1M);
126 BENCHMARK(Skip100_ForwardQ128_1M) {
127 bmSkip<bm::Reader>(bm::list, bm::data, 100, bm::k1M);
130 BENCHMARK(Skip1000_ForwardQ128_1M) {
131 bmSkip<bm::Reader>(bm::list, bm::data, 1000, bm::k1M);
134 BENCHMARK(Jump_ForwardQ128_1M) {
135 bmJump<bm::Reader>(bm::list, bm::data, bm::order, bm::k1M);
138 BENCHMARK_DRAW_LINE();
140 BENCHMARK(SkipTo1_SkipQ128_1M) {
141 bmSkipTo<bm::Reader>(bm::list, bm::data, 1, bm::k1M);
144 BENCHMARK(SkipTo10_SkipQ128_1M) {
145 bmSkipTo<bm::Reader>(bm::list, bm::data, 10, bm::k1M);
148 BENCHMARK(SkipTo100_SkipQ128_1M) {
149 bmSkipTo<bm::Reader>(bm::list, bm::data, 100, bm::k1M);
152 BENCHMARK(SkipTo1000_SkipQ128_1M) {
153 bmSkipTo<bm::Reader>(bm::list, bm::data, 1000, bm::k1M);
156 BENCHMARK(JumpTo_SkipQ128_1M) {
157 bmJumpTo<bm::Reader>(bm::list, bm::data, bm::order, bm::k1M);
160 BENCHMARK_DRAW_LINE();
162 BENCHMARK(Encode_10) {
163 auto list = bm::Encoder::encode(bm::encodeSmallData.begin(),
164 bm::encodeSmallData.end());
168 BENCHMARK(Encode_1M) {
169 auto list = bm::Encoder::encode(bm::encodeLargeData.begin(),
170 bm::encodeLargeData.end());
175 Intel(R) Xeon(R) CPU E5-2660 @ 2.7GHz (turbo on), using instructions::Fast.
177 ============================================================================
178 folly/experimental/test/EliasFanoCodingTest.cpp relative time/iter iters/s
179 ============================================================================
180 Next_1M 4.61ms 216.70
181 Skip1_ForwarQ128_1M 5.33ms 187.71
182 Skip10_ForwarQ128_1M 14.23ms 70.26
183 Skip100_ForwardQ128_1M 29.10ms 34.37
184 Skip1000_ForwardQ128_1M 21.15ms 47.28
185 Jump_ForwardQ128_1M 46.30ms 21.60
186 ----------------------------------------------------------------------------
187 SkipTo1_SkipQ128_1M 12.03ms 83.15
188 SkipTo10_SkipQ128_1M 36.11ms 27.69
189 SkipTo100_SkipQ128_1M 42.91ms 23.30
190 SkipTo1000_SkipQ128_1M 36.92ms 27.08
191 JumpTo_SkipQ128_1M 78.51ms 12.74
192 ----------------------------------------------------------------------------
193 Encode_10 199.19ns 5.02M
194 Encode_1M 8.82ms 113.37
195 ============================================================================
198 int main(int argc, char** argv) {
199 testing::InitGoogleTest(&argc, argv);
200 gflags::ParseCommandLineFlags(&argc, &argv, true);
202 auto ret = RUN_ALL_TESTS();
203 if (ret == 0 && FLAGS_benchmark) {
205 folly::runBenchmarks();