2 * Copyright 2015 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.
22 #include <folly/Benchmark.h>
23 #include <folly/experimental/EliasFanoCoding.h>
24 #include <folly/experimental/Select64.h>
25 #include <folly/experimental/test/CodingTestUtils.h>
27 using namespace folly::compression;
30 #define EF_TEST_ARCH Default
31 #endif // EF_TEST_ARCH
33 class EliasFanoCodingTest : public ::testing::Test {
36 typedef EliasFanoEncoderV2<uint32_t, size_t> Encoder;
37 typedef EliasFanoReader<Encoder> Reader;
38 testEmpty<Reader, Encoder>();
41 template <size_t kSkipQuantum, size_t kForwardQuantum>
43 typedef EliasFanoEncoderV2<
44 uint32_t, uint32_t, kSkipQuantum, kForwardQuantum> Encoder;
45 typedef EliasFanoReader<Encoder, instructions::EF_TEST_ARCH> Reader;
46 testAll<Reader, Encoder>({0});
47 testAll<Reader, Encoder>(generateRandomList(100 * 1000, 10 * 1000 * 1000));
48 testAll<Reader, Encoder>(generateSeqList(1, 100000, 100));
52 TEST_F(EliasFanoCodingTest, Empty) {
56 TEST_F(EliasFanoCodingTest, Simple) {
60 TEST_F(EliasFanoCodingTest, SkipPointers) {
64 TEST_F(EliasFanoCodingTest, ForwardPointers) {
68 TEST_F(EliasFanoCodingTest, SkipForwardPointers) {
69 doTestAll<128, 128>();
74 constexpr size_t k1M = 1000000;
76 typedef EliasFanoEncoderV2<uint32_t, uint32_t, 128, 128> Encoder;
77 typedef EliasFanoReader<Encoder> Reader;
79 std::vector<uint32_t> data;
80 std::vector<size_t> order;
82 std::vector<uint32_t> encodeSmallData;
83 std::vector<uint32_t> encodeLargeData;
85 typename Encoder::MutableCompressedList list;
90 data = generateRandomList(100 * 1000, 10 * 1000 * 1000, gen);
91 list = Encoder::encode(data.begin(), data.end());
93 order.resize(data.size());
94 std::iota(order.begin(), order.end(), size_t());
95 std::shuffle(order.begin(), order.end(), gen);
97 encodeSmallData = generateRandomList(10, 100 * 1000, gen);
98 encodeLargeData = generateRandomList(1000 * 1000, 100 * 1000 * 1000, gen);
107 BENCHMARK(Next, iters) {
108 bmNext<bm::Reader>(bm::list, bm::data, iters);
111 size_t Skip_ForwardQ128(size_t iters, size_t logAvgSkip) {
112 bmSkip<bm::Reader>(bm::list, bm::data, logAvgSkip, iters);
116 BENCHMARK_NAMED_PARAM_MULTI(Skip_ForwardQ128, 1, 0)
117 BENCHMARK_NAMED_PARAM_MULTI(Skip_ForwardQ128, 2, 1)
118 BENCHMARK_NAMED_PARAM_MULTI(Skip_ForwardQ128, 4_pm_1, 2)
119 BENCHMARK_NAMED_PARAM_MULTI(Skip_ForwardQ128, 16_pm_4, 4)
120 BENCHMARK_NAMED_PARAM_MULTI(Skip_ForwardQ128, 64_pm_16, 6)
121 BENCHMARK_NAMED_PARAM_MULTI(Skip_ForwardQ128, 256_pm_64, 8)
122 BENCHMARK_NAMED_PARAM_MULTI(Skip_ForwardQ128, 1024_pm_256, 10)
124 BENCHMARK(Jump_ForwardQ128, iters) {
125 bmJump<bm::Reader>(bm::list, bm::data, bm::order, iters);
128 BENCHMARK_DRAW_LINE();
130 size_t SkipTo_SkipQ128(size_t iters, size_t logAvgSkip) {
131 bmSkipTo<bm::Reader>(bm::list, bm::data, logAvgSkip, iters);
135 BENCHMARK_NAMED_PARAM_MULTI(SkipTo_SkipQ128, 1, 0)
136 BENCHMARK_NAMED_PARAM_MULTI(SkipTo_SkipQ128, 2, 1)
137 BENCHMARK_NAMED_PARAM_MULTI(SkipTo_SkipQ128, 4_pm_1, 2)
138 BENCHMARK_NAMED_PARAM_MULTI(SkipTo_SkipQ128, 16_pm_4, 4)
139 BENCHMARK_NAMED_PARAM_MULTI(SkipTo_SkipQ128, 64_pm_16, 6)
140 BENCHMARK_NAMED_PARAM_MULTI(SkipTo_SkipQ128, 256_pm_64, 8)
141 BENCHMARK_NAMED_PARAM_MULTI(SkipTo_SkipQ128, 1024_pm_256, 10)
143 BENCHMARK(JumpTo_SkipQ128, iters) {
144 bmJumpTo<bm::Reader>(bm::list, bm::data, bm::order, iters);
147 BENCHMARK_DRAW_LINE();
149 BENCHMARK(Encode_10) {
150 auto list = bm::Encoder::encode(bm::encodeSmallData.begin(),
151 bm::encodeSmallData.end());
156 auto list = bm::Encoder::encode(bm::encodeLargeData.begin(),
157 bm::encodeLargeData.end());
161 BENCHMARK_DRAW_LINE();
163 BENCHMARK(Select64, iters) {
164 typedef instructions::EF_TEST_ARCH instr;
165 constexpr uint64_t kPrime = uint64_t(-59);
166 for (uint64_t x = kPrime, i = 0; i < iters; x *= kPrime, i += 1) {
167 size_t w = instr::popcount(x);
168 folly::doNotOptimizeAway(folly::select64<instr>(x, w - 1));
173 Intel(R) Xeon(R) CPU E5-2673 v3 @ 2.40GHz (turbo off),
174 using instructions::Haswell and GCC 4.9 with --bm_min_usec 100000.
175 ============================================================================
176 folly/experimental/test/EliasFanoCodingTest.cpp relative time/iter iters/s
177 ============================================================================
179 Skip_ForwardQ128(1) 3.92ns 255.28M
180 Skip_ForwardQ128(2) 5.08ns 197.04M
181 Skip_ForwardQ128(4_pm_1) 7.04ns 142.02M
182 Skip_ForwardQ128(16_pm_4) 19.68ns 50.82M
183 Skip_ForwardQ128(64_pm_16) 27.58ns 36.26M
184 Skip_ForwardQ128(256_pm_64) 32.49ns 30.78M
185 Skip_ForwardQ128(1024_pm_256) 33.39ns 29.95M
186 Jump_ForwardQ128 34.05ns 29.37M
187 ----------------------------------------------------------------------------
188 SkipTo_SkipQ128(1) 4.42ns 226.49M
189 SkipTo_SkipQ128(2) 8.58ns 116.55M
190 SkipTo_SkipQ128(4_pm_1) 11.43ns 87.50M
191 SkipTo_SkipQ128(16_pm_4) 31.19ns 32.06M
192 SkipTo_SkipQ128(64_pm_16) 43.88ns 22.79M
193 SkipTo_SkipQ128(256_pm_64) 49.08ns 20.37M
194 SkipTo_SkipQ128(1024_pm_256) 52.24ns 19.14M
195 JumpTo_SkipQ128 54.61ns 18.31M
196 ----------------------------------------------------------------------------
197 Encode_10 117.24ns 8.53M
199 ----------------------------------------------------------------------------
200 Select64 8.04ns 124.35M
201 ============================================================================
204 int main(int argc, char** argv) {
205 testing::InitGoogleTest(&argc, argv);
206 gflags::ParseCommandLineFlags(&argc, &argv, true);
208 auto ret = RUN_ALL_TESTS();
209 if (ret == 0 && FLAGS_benchmark) {
211 folly::runBenchmarks();