1+ // Licensed to the Apache Software Foundation (ASF) under one
2+ // or more contributor license agreements. See the NOTICE file
3+ // distributed with this work for additional information
4+ // regarding copyright ownership. The ASF licenses this file
5+ // to you under the Apache License, Version 2.0 (the
6+ // "License"); you may not use this file except in compliance
7+ // with the License. You may obtain a copy of the License at
8+ //
9+ // http://www.apache.org/licenses/LICENSE-2.0
10+ //
11+ // Unless required by applicable law or agreed to in writing,
12+ // software distributed under the License is distributed on an
13+ // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14+ // KIND, either express or implied. See the License for the
15+ // specific language governing permissions and limitations
16+ // under the License.
17+
18+ #pragma once
19+
20+ #include < benchmark/benchmark.h>
21+
22+ #include < random>
23+ #include < vector>
24+
25+ #include " util/frame_of_reference_coding.h"
26+
27+ namespace doris {
28+
29+ // original bit_unpack function
30+ template <typename T>
31+ void bit_unpack (const uint8_t * input, uint8_t in_num, int bit_width, T* output) {
32+ unsigned char in_mask = 0x80 ;
33+ int bit_index = 0 ;
34+ while (in_num > 0 ) {
35+ *output = 0 ;
36+ for (int i = 0 ; i < bit_width; i++) {
37+ if (bit_index > 7 ) {
38+ input++;
39+ bit_index = 0 ;
40+ }
41+ *output |= ((T)((*input & (in_mask >> bit_index)) >> (7 - bit_index)))
42+ << (bit_width - i - 1 );
43+ bit_index++;
44+ }
45+ output++;
46+ in_num--;
47+ }
48+ }
49+
50+ static void BM_BitUnpack (benchmark::State& state) {
51+ int w = state.range (0 );
52+ int n = 255 ;
53+
54+ std::default_random_engine e;
55+ std::uniform_int_distribution<__int128_t > u;
56+ ForEncoder<__int128_t > encoder (nullptr );
57+ ForDecoder<__int128_t > decoder (nullptr , 0 );
58+ std::vector<__int128_t > test_data (n);
59+ __int128_t in_mask = (((__int128_t )1 ) << w) - 1 ;
60+
61+ for (int i = 0 ; i < n; i++) {
62+ test_data[i] = u (e) & in_mask;
63+ }
64+ std::vector<uint8_t > o ((n * w + 7 ) / 8 );
65+ encoder.bit_pack (test_data.data (), n, w, o.data ());
66+
67+ std::vector<__int128_t > output (n);
68+
69+ for (auto _ : state) {
70+ benchmark::DoNotOptimize (o.data ());
71+ benchmark::DoNotOptimize (output.data ());
72+ bit_unpack (o.data (), n, w, output.data ());
73+ benchmark::ClobberMemory ();
74+ }
75+
76+ int64_t size = o.size ();
77+ state.SetBytesProcessed (int64_t (state.iterations ()) * size);
78+ }
79+
80+ static void BM_BitUnpackOptimized (benchmark::State& state) {
81+ int w = state.range (0 );
82+ int n = 255 ;
83+
84+ std::default_random_engine e;
85+ std::uniform_int_distribution<__int128_t > u;
86+
87+ ForEncoder<__int128_t > encoder (nullptr );
88+ ForDecoder<__int128_t > decoder (nullptr , 0 );
89+ std::vector<__int128_t > test_data (n);
90+ __int128_t in_mask = (((__int128_t )1 ) << w) - 1 ;
91+
92+ for (int i = 0 ; i < n; i++) {
93+ test_data[i] = u (e) & in_mask;
94+ }
95+ std::vector<uint8_t > o ((n * w + 7 ) / 8 );
96+ encoder.bit_pack (test_data.data (), n, w, o.data ());
97+
98+ std::vector<__int128_t > output (n);
99+
100+ for (auto _ : state) {
101+ benchmark::DoNotOptimize (o.data ());
102+ benchmark::DoNotOptimize (output.data ());
103+ decoder.bit_unpack (o.data (), n, w, output.data ());
104+ benchmark::ClobberMemory ();
105+ }
106+
107+ int64_t size = o.size ();
108+ state.SetBytesProcessed (int64_t (state.iterations ()) * size);
109+ }
110+
111+ BENCHMARK (BM_BitUnpack)->DenseRange (1 , 127 )->Unit(benchmark::kNanosecond );
112+ BENCHMARK (BM_BitUnpackOptimized)->DenseRange (1 , 127 )->Unit(benchmark::kNanosecond );
113+ } // namespace doris
0 commit comments