GCC Code Coverage Report


Directory: cvmfs/
File: cvmfs/util/algorithm.h
Date: 2026-10-25 02:40:14
Exec Total Coverage
Lines: 42 50 84.0%
Branches: 27 41 65.9%

Line Branch Exec Source
1 /**
2 * This file is part of the CernVM File System.
3 */
4
5 #ifndef CVMFS_UTIL_ALGORITHM_H_
6 #define CVMFS_UTIL_ALGORITHM_H_
7
8 #include <sys/time.h>
9
10 #include <algorithm>
11 #include <atomic>
12 #include <cassert>
13 #include <cstddef>
14 #include <cstdint>
15 #include <memory>
16 #include <string>
17 #include <utility>
18 #include <vector>
19
20 #include "util/export.h"
21 #include "util/murmur.hxx"
22 #include "util/platform.h"
23 #include "util/prng.h"
24 #include "util/single_copy.h"
25
26 #ifdef CVMFS_NAMESPACE_GUARD
27 namespace CVMFS_NAMESPACE_GUARD {
28 #endif
29
30
31 CVMFS_EXPORT double DiffTimeSeconds(struct timeval start, struct timeval end);
32
33 // Bitfield manipulation for different integer types T
34 template<typename T>
35 112 inline void SetBit(unsigned int bit, T *field) {
36 112 *field |= static_cast<T>(1) << bit;
37 112 }
38
39 template<typename T>
40 112 inline void ClearBit(unsigned int bit, T *field) {
41 112 *field &= ~(static_cast<T>(1) << bit);
42 112 }
43
44 template<typename T>
45 168 inline bool TestBit(unsigned int bit, const T field) {
46 168 return field & (static_cast<T>(1) << bit);
47 }
48
49
50 /**
51 * Knuth's random shuffle algorithm.
52 */
53 template<typename T>
54 65 std::vector<T> Shuffle(const std::vector<T> &input, Prng *prng) {
55 65 std::vector<T> shuffled(input);
56 65 unsigned N = shuffled.size();
57 // No shuffling for the last element
58
2/2
✓ Branch 0 taken 450094 times.
✓ Branch 1 taken 47 times.
631311 for (unsigned i = 0; i < N; ++i) {
59 631246 const unsigned swap_idx = i + prng->Next(N - i);
60 631246 std::swap(shuffled[i], shuffled[swap_idx]);
61 }
62 65 return shuffled;
63 }
64
65
66 /**
67 * Sorts the vector tractor and applies the same permutation to towed. Both
68 * vectors have to be of the same size. Type T must be sortable (< operator).
69 * Uses insertion sort (n^2), only efficient for small vectors.
70 */
71 template<typename T, typename U>
72 203 void SortTeam(std::vector<T> *tractor, std::vector<U> *towed) {
73
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 203 times.
203 assert(tractor);
74
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 203 times.
203 assert(towed);
75
1/2
✗ Branch 2 not taken.
✓ Branch 3 taken 203 times.
203 assert(tractor->size() == towed->size());
76 203 int N = tractor->size();
77
78 // Insertion sort on both, tractor and towed
79
3/4
✓ Branch 0 taken 1289 times.
✓ Branch 1 taken 203 times.
✓ Branch 2 taken 95 times.
✗ Branch 3 not taken.
1587 for (int i = 1; i < N; ++i) {
80
1/2
✓ Branch 2 taken 1289 times.
✗ Branch 3 not taken.
1384 T val_tractor = (*tractor)[i];
81
1/2
✓ Branch 2 taken 95 times.
✗ Branch 3 not taken.
1384 U val_towed = (*towed)[i];
82 int pos;
83
7/7
✓ Branch 0 taken 15851 times.
✓ Branch 1 taken 80 times.
✓ Branch 3 taken 57 times.
✓ Branch 4 taken 14547 times.
✓ Branch 5 taken 1304 times.
✓ Branch 6 taken 14585 times.
✓ Branch 7 taken 1289 times.
15931 for (pos = i - 1; (pos >= 0) && ((*tractor)[pos] > val_tractor); --pos) {
84
1/2
✓ Branch 3 taken 14490 times.
✗ Branch 4 not taken.
14547 (*tractor)[pos + 1] = (*tractor)[pos];
85
1/2
✓ Branch 3 taken 57 times.
✗ Branch 4 not taken.
14547 (*towed)[pos + 1] = (*towed)[pos];
86 }
87
1/2
✓ Branch 2 taken 1289 times.
✗ Branch 3 not taken.
1384 (*tractor)[pos + 1] = val_tractor;
88
1/2
✓ Branch 2 taken 95 times.
✗ Branch 3 not taken.
1384 (*towed)[pos + 1] = val_towed;
89 }
90 203 }
91
92
93 template<typename hashed_type>
94 struct hash_murmur {
95 ✗ size_t operator()(const hashed_type key) const {
96 #ifdef __x86_64__
97 ✗ return MurmurHash64A(&key, sizeof(key), 0x9ce603115bba659bLLU);
98 #else
99 return MurmurHash2(&key, sizeof(key), 0x07387a4f);
100 #endif
101 }
102 };
103
104
105 /**
106 * Very simple StopWatch implementation. Currently the implementation does not
107 * allow a restart of a stopped watch. You should always reset the clock before
108 * you reuse it.
109 *
110 * Stopwatch watch();
111 * watch.Start();
112 * // do nasty thing
113 * watch.Stop();
114 * printf("%f", watch.GetTime());
115 */
116 class CVMFS_EXPORT StopWatch : SingleCopy {
117 public:
118 41 StopWatch() : running_(false) { }
119
120 void Start();
121 void Stop();
122 void Reset();
123
124 double GetTime() const;
125
126 private:
127 bool running_;
128 timeval start_, end_;
129 };
130
131
132 /**
133 * Log2Histogram is a simple implementation of
134 * log2 histogram data structure which stores
135 * and prints log2 histogram. It is used for
136 * getting and printing latency metrics of
137 * CVMFS fuse calls.
138 *
139 * Log2Histogram hist(2);
140 * hist.Add(1);
141 * hist.Add(2);
142 * hist.PrintLog2Histogram();
143 */
144
145 class CVMFS_EXPORT Log2Histogram {
146 friend class UTLog2Histogram;
147
148 public:
149 explicit Log2Histogram(unsigned int nbins);
150
151 10485980 void Add(uint64_t value) {
152 unsigned int i;
153 10485980 const unsigned int n = this->bins_.size() - 1;
154
155
2/2
✓ Branch 0 taken 157283170 times.
✓ Branch 1 taken 50 times.
157283220 for (i = 1; i <= n; i++) {
156
2/2
✓ Branch 1 taken 10485930 times.
✓ Branch 2 taken 146797240 times.
157283170 if (value < this->boundary_values_[i]) {
157 10485930 (this->bins_[i]->fetch_add(1));
158 10485930 return;
159 }
160 }
161
162 50 (this->bins_[0]->fetch_add(1)); // add to overflow bin.
163 }
164
165 /**
166 * Returns the total number of elements in the histogram
167 */
168 130 inline uint64_t N() {
169 130 uint64_t n = 0;
170 unsigned int i;
171
2/2
✓ Branch 1 taken 2190 times.
✓ Branch 2 taken 130 times.
2320 for (i = 0; i <= this->bins_.size() - 1; i++) {
172 4380 n += static_cast<unsigned int>((this->bins_[i]->load()));
173 }
174 130 return n;
175 }
176
177 /**
178 * compute the quantile of order n
179 */
180 unsigned int GetQuantile(float n);
181
182 std::string ToString();
183
184 void PrintLog2Histogram();
185
186 private:
187 std::vector<std::unique_ptr<std::atomic<int32_t> > > bins_;
188 // boundary_values_ handle the largest value a certain
189 // bin can store in itself.
190 std::vector<unsigned int> boundary_values_;
191 };
192
193 /**
194 * UTLog2Histogram class is a helper for the unit tests
195 * to extract internals from Log2Histogram.
196 */
197 class CVMFS_EXPORT UTLog2Histogram {
198 public:
199 const std::vector<std::unique_ptr<std::atomic<int32_t> > > &GetBins(
200 const Log2Histogram &h);
201 };
202
203
204 class CVMFS_EXPORT HighPrecisionTimer : SingleCopy {
205 public:
206 static bool g_is_enabled; // false by default
207
208 ✗ explicit HighPrecisionTimer(Log2Histogram *recorder)
209 ✗ : timestamp_start_(g_is_enabled ? platform_monotonic_time_ns() : 0)
210 ✗ , recorder_(recorder) { }
211
212 ✗ ~HighPrecisionTimer() {
213 ✗ if (g_is_enabled)
214 ✗ recorder_->Add(platform_monotonic_time_ns() - timestamp_start_);
215 }
216
217 private:
218 uint64_t timestamp_start_;
219 Log2Histogram *recorder_;
220 };
221
222 #ifdef CVMFS_NAMESPACE_GUARD
223 } // namespace CVMFS_NAMESPACE_GUARD
224 #endif
225
226 #endif // CVMFS_UTIL_ALGORITHM_H_
227
228