pub struct HyperCounter<K, V, H = RandomState>{ /* private fields */ }Implementations§
Source§impl<K, V, H> HyperCounter<K, V, H>
impl<K, V, H> HyperCounter<K, V, H>
Sourcepub fn new() -> Self
pub fn new() -> Self
Examples found in repository?
41fn load_ops_per_second_single_threaded_fetch_add_single_key() {
42 let counter: HyperCounter<i32, AtomicI32> = HyperCounter::new();
43
44 let now = Instant::now();
45 let mut i = 0;
46
47 loop {
48 counter.fetch_add(1, 1, Ordering::Relaxed);
49 i += 1;
50
51 if now.elapsed().as_secs() >= 1 {
52 break;
53 }
54 }
55
56 println!("Single-threaded single-key load ops/sec: {}", pretty_int(i));
57}
58
59fn load_ops_per_second_single_threaded_fetch_add_multi_key() {
60 let counter: HyperCounter<i32, AtomicI32> = HyperCounter::new();
61
62 let now = Instant::now();
63 let mut i = 0;
64
65 loop {
66 let key = i % 1000;
67 counter.fetch_add(key, 1, Ordering::Relaxed);
68 i += 1;
69
70 if now.elapsed().as_secs() >= 1 {
71 break;
72 }
73 }
74
75 println!("Single-threaded multi-key load ops/sec: {}", pretty_int(i));
76}
77
78fn load_ops_per_second_single_threaded_insert() {
79 let counter: HyperCounter<i32, AtomicI32> = HyperCounter::new();
80
81 let now = Instant::now();
82 let mut i = 0;
83
84 loop {
85 counter.fetch_add(i, 1, Ordering::Relaxed);
86 i += 1;
87
88 if now.elapsed().as_secs() >= 1 {
89 break;
90 }
91 }
92
93 println!("Single-threaded insert ops/sec: {}", pretty_int(i));
94}
95
96fn load_ops_per_second_single_threaded_remove() {
97 let counter: HyperCounter<i32, AtomicI32> = HyperCounter::new();
98
99 for i in 0..2_000_000 {
100 counter.fetch_add(i, 1, Ordering::Relaxed);
101 }
102
103 let now = Instant::now();
104 let mut i = 0;
105
106 loop {
107 counter.fetch_sub(i, 1, Ordering::Relaxed);
108 i += 1;
109
110 if now.elapsed().as_secs() >= 1 {
111 break;
112 }
113 }
114
115 println!("Single-threaded remove ops/sec: {}", pretty_int(i));
116}
117
118fn load_ops_per_second_single_threaded_churn() {
119 let counter: HyperCounter<i32, AtomicI32> = HyperCounter::new();
120
121 let now = Instant::now();
122 let mut i = 0;
123
124 loop {
125 if i % 2 == 0 {
126 counter.fetch_add(i, 1, Ordering::Relaxed);
127 } else {
128 counter.fetch_sub(i, 1, Ordering::Relaxed);
129 }
130
131 i += 1;
132
133 if now.elapsed().as_secs() >= 1 {
134 break;
135 }
136 }
137
138 println!("Single-threaded churn op/s: {}", pretty_int(i));
139}
140
141fn load_ops_per_second_multi_threaded_fetch_add_single_key() {
142 let counter: Arc<HyperCounter<i32, AtomicI32>> = Arc::new(HyperCounter::new());
143
144 let mut handles = vec![];
145
146 for _ in 0..THREADS {
147 let counter = counter.clone();
148
149 let handle = std::thread::spawn(move || {
150 let now = Instant::now();
151
152 loop {
153 counter.fetch_add(1, 1, Ordering::Relaxed);
154
155 if now.elapsed().as_secs() >= 1 {
156 break;
157 }
158 }
159 });
160
161 handles.push(handle);
162 }
163
164 for handle in handles {
165 handle.join().unwrap();
166 }
167
168 let i = counter.load(&1, Ordering::Relaxed);
169
170 println!("Multi-threaded single-key load ops/sec: {}", pretty_int(i));
171}
172
173fn load_ops_per_second_multi_threaded_fetch_add_multi_key() {
174 let counter: Arc<HyperCounter<i32, AtomicI32>> = Arc::new(HyperCounter::new());
175
176 let mut handles = vec![];
177
178 for thread_id in 0..THREADS {
179 let counter = counter.clone();
180
181 let handle = std::thread::spawn(move || {
182 let now = Instant::now();
183
184 for i in 0.. {
185 let key = (i + thread_id) % 1000;
186 counter.fetch_add(key, 1, Ordering::Relaxed);
187
188 if now.elapsed().as_secs() >= 1 {
189 break;
190 }
191 }
192 });
193
194 handles.push(handle);
195 }
196
197 for handle in handles {
198 handle.join().unwrap();
199 }
200
201 let mut i = 0;
202
203 for key in 0..1000 {
204 i += counter.load(&key, Ordering::Relaxed);
205 }
206
207 println!("Multi-threaded multi-key load ops/sec: {}", pretty_int(i));
208}
209
210fn load_ops_per_second_multi_threaded_insert() {
211 let counter: Arc<HyperCounter<i32, AtomicI32>> = Arc::new(HyperCounter::new());
212
213 let mut handles = vec![];
214
215 for thread_id in 0..THREADS {
216 let counter = counter.clone();
217
218 let handle = std::thread::spawn(move || {
219 let now = Instant::now();
220
221 for i in 0.. {
222 let key = i + thread_id * 1_000_000;
223 counter.fetch_add(key, 1, Ordering::Relaxed);
224
225 if now.elapsed().as_secs() >= 1 {
226 break;
227 }
228 }
229 });
230
231 handles.push(handle);
232 }
233
234 for handle in handles {
235 handle.join().unwrap();
236 }
237
238 let i = counter.len();
239
240 println!("Multi-threaded insert ops/sec: {}", pretty_int(i as i32));
241}
242
243fn load_ops_per_second_multi_threaded_remove() {
244 let counter: Arc<HyperCounter<i32, AtomicI32>> = Arc::new(HyperCounter::new());
245
246 for i in 0..8_000_000 {
247 counter.fetch_add(i, 1, Ordering::Relaxed);
248 }
249
250 let mut handles = vec![];
251
252 for thread_id in 0..THREADS {
253 let counter = counter.clone();
254
255 let handle = std::thread::spawn(move || {
256 let now = Instant::now();
257
258 for i in 0.. {
259 let key = i + thread_id * 1_000_000;
260 counter.fetch_sub(key, 1, Ordering::Relaxed);
261
262 if now.elapsed().as_secs() >= 1 {
263 break;
264 }
265 }
266 });
267
268 handles.push(handle);
269 }
270
271 for handle in handles {
272 handle.join().unwrap();
273 }
274
275 let i = counter.len();
276
277 println!(
278 "Multi-threaded remove ops/sec: {}",
279 pretty_int(8_000_000 - i as i32)
280 );
281}
282
283fn load_ops_per_second_multi_threaded_churn() {
284 let counter: Arc<HyperCounter<i32, AtomicI32>> = Arc::new(HyperCounter::new());
285
286 let mut handles = vec![];
287
288 for _ in 0..THREADS {
289 let counter = counter.clone();
290
291 let handle = std::thread::spawn(move || {
292 let now = Instant::now();
293 let mut i = 0;
294
295 loop {
296 if i % 2 == 0 {
297 counter.fetch_add(1, 1, Ordering::Relaxed);
298 } else {
299 counter.fetch_sub(1, 1, Ordering::Relaxed);
300 }
301
302 i += 1;
303
304 if now.elapsed().as_secs() >= 1 {
305 break;
306 }
307 }
308
309 i
310 });
311
312 handles.push(handle);
313 }
314
315 let mut i = 0;
316
317 for handle in handles {
318 i += handle.join().unwrap();
319 }
320
321 println!("Multi-threaded churn op/s: {}", pretty_int(i));
322}Sourcepub fn len(&self) -> usize
pub fn len(&self) -> usize
Returns the current amount of occupied entries in the HyperCounter.
Returns:
usize- The current length.
Examples found in repository?
210fn load_ops_per_second_multi_threaded_insert() {
211 let counter: Arc<HyperCounter<i32, AtomicI32>> = Arc::new(HyperCounter::new());
212
213 let mut handles = vec![];
214
215 for thread_id in 0..THREADS {
216 let counter = counter.clone();
217
218 let handle = std::thread::spawn(move || {
219 let now = Instant::now();
220
221 for i in 0.. {
222 let key = i + thread_id * 1_000_000;
223 counter.fetch_add(key, 1, Ordering::Relaxed);
224
225 if now.elapsed().as_secs() >= 1 {
226 break;
227 }
228 }
229 });
230
231 handles.push(handle);
232 }
233
234 for handle in handles {
235 handle.join().unwrap();
236 }
237
238 let i = counter.len();
239
240 println!("Multi-threaded insert ops/sec: {}", pretty_int(i as i32));
241}
242
243fn load_ops_per_second_multi_threaded_remove() {
244 let counter: Arc<HyperCounter<i32, AtomicI32>> = Arc::new(HyperCounter::new());
245
246 for i in 0..8_000_000 {
247 counter.fetch_add(i, 1, Ordering::Relaxed);
248 }
249
250 let mut handles = vec![];
251
252 for thread_id in 0..THREADS {
253 let counter = counter.clone();
254
255 let handle = std::thread::spawn(move || {
256 let now = Instant::now();
257
258 for i in 0.. {
259 let key = i + thread_id * 1_000_000;
260 counter.fetch_sub(key, 1, Ordering::Relaxed);
261
262 if now.elapsed().as_secs() >= 1 {
263 break;
264 }
265 }
266 });
267
268 handles.push(handle);
269 }
270
271 for handle in handles {
272 handle.join().unwrap();
273 }
274
275 let i = counter.len();
276
277 println!(
278 "Multi-threaded remove ops/sec: {}",
279 pretty_int(8_000_000 - i as i32)
280 );
281}Sourcepub fn is_empty(&self) -> bool
pub fn is_empty(&self) -> bool
Checks if the HyperCounter is empty.
Returns:
true- if the HyperCounter is empty.false- otherwise.
Sourcepub fn load(&self, key: &K, ordering: Ordering) -> V::Primitive
pub fn load(&self, key: &K, ordering: Ordering) -> V::Primitive
Atomically loads the value for the given key.
Arguments:
key- The key to load.ordering- The memory ordering to use.
Returns:
- [
V::Primitive] - The current value associated with the key, or zero if the key is missing.
Examples found in repository?
141fn load_ops_per_second_multi_threaded_fetch_add_single_key() {
142 let counter: Arc<HyperCounter<i32, AtomicI32>> = Arc::new(HyperCounter::new());
143
144 let mut handles = vec![];
145
146 for _ in 0..THREADS {
147 let counter = counter.clone();
148
149 let handle = std::thread::spawn(move || {
150 let now = Instant::now();
151
152 loop {
153 counter.fetch_add(1, 1, Ordering::Relaxed);
154
155 if now.elapsed().as_secs() >= 1 {
156 break;
157 }
158 }
159 });
160
161 handles.push(handle);
162 }
163
164 for handle in handles {
165 handle.join().unwrap();
166 }
167
168 let i = counter.load(&1, Ordering::Relaxed);
169
170 println!("Multi-threaded single-key load ops/sec: {}", pretty_int(i));
171}
172
173fn load_ops_per_second_multi_threaded_fetch_add_multi_key() {
174 let counter: Arc<HyperCounter<i32, AtomicI32>> = Arc::new(HyperCounter::new());
175
176 let mut handles = vec![];
177
178 for thread_id in 0..THREADS {
179 let counter = counter.clone();
180
181 let handle = std::thread::spawn(move || {
182 let now = Instant::now();
183
184 for i in 0.. {
185 let key = (i + thread_id) % 1000;
186 counter.fetch_add(key, 1, Ordering::Relaxed);
187
188 if now.elapsed().as_secs() >= 1 {
189 break;
190 }
191 }
192 });
193
194 handles.push(handle);
195 }
196
197 for handle in handles {
198 handle.join().unwrap();
199 }
200
201 let mut i = 0;
202
203 for key in 0..1000 {
204 i += counter.load(&key, Ordering::Relaxed);
205 }
206
207 println!("Multi-threaded multi-key load ops/sec: {}", pretty_int(i));
208}Sourcepub fn swap(
&self,
key: K,
new_value: V::Primitive,
ordering: Ordering,
) -> V::Primitive
pub fn swap( &self, key: K, new_value: V::Primitive, ordering: Ordering, ) -> V::Primitive
Atomically swaps the value for the given key.
If the new value is zero, the entry is removed.
If the key is missing, a new entry is created with the new value.
Arguments:
key- The key to swap.new_value- The new value to set.ordering- The memory ordering to use.
Returns:
- [
V::Primitive] - The previous value associated with the key. (before swap)
Sourcepub fn fetch_add(
&self,
key: K,
value: V::Primitive,
ordering: Ordering,
) -> V::Primitive
pub fn fetch_add( &self, key: K, value: V::Primitive, ordering: Ordering, ) -> V::Primitive
Atomically adds a value to the counter for the given key.
If the key ends up being zero after addition, the entry is removed.
If the key is missing, a new entry is created with the given value.
Arguments:
key- The key to add to.value- The value to add.ordering- The memory ordering to use.
Returns:
- [
V::Primitive] - The previous value associated with the key. (before addition)
Examples found in repository?
41fn load_ops_per_second_single_threaded_fetch_add_single_key() {
42 let counter: HyperCounter<i32, AtomicI32> = HyperCounter::new();
43
44 let now = Instant::now();
45 let mut i = 0;
46
47 loop {
48 counter.fetch_add(1, 1, Ordering::Relaxed);
49 i += 1;
50
51 if now.elapsed().as_secs() >= 1 {
52 break;
53 }
54 }
55
56 println!("Single-threaded single-key load ops/sec: {}", pretty_int(i));
57}
58
59fn load_ops_per_second_single_threaded_fetch_add_multi_key() {
60 let counter: HyperCounter<i32, AtomicI32> = HyperCounter::new();
61
62 let now = Instant::now();
63 let mut i = 0;
64
65 loop {
66 let key = i % 1000;
67 counter.fetch_add(key, 1, Ordering::Relaxed);
68 i += 1;
69
70 if now.elapsed().as_secs() >= 1 {
71 break;
72 }
73 }
74
75 println!("Single-threaded multi-key load ops/sec: {}", pretty_int(i));
76}
77
78fn load_ops_per_second_single_threaded_insert() {
79 let counter: HyperCounter<i32, AtomicI32> = HyperCounter::new();
80
81 let now = Instant::now();
82 let mut i = 0;
83
84 loop {
85 counter.fetch_add(i, 1, Ordering::Relaxed);
86 i += 1;
87
88 if now.elapsed().as_secs() >= 1 {
89 break;
90 }
91 }
92
93 println!("Single-threaded insert ops/sec: {}", pretty_int(i));
94}
95
96fn load_ops_per_second_single_threaded_remove() {
97 let counter: HyperCounter<i32, AtomicI32> = HyperCounter::new();
98
99 for i in 0..2_000_000 {
100 counter.fetch_add(i, 1, Ordering::Relaxed);
101 }
102
103 let now = Instant::now();
104 let mut i = 0;
105
106 loop {
107 counter.fetch_sub(i, 1, Ordering::Relaxed);
108 i += 1;
109
110 if now.elapsed().as_secs() >= 1 {
111 break;
112 }
113 }
114
115 println!("Single-threaded remove ops/sec: {}", pretty_int(i));
116}
117
118fn load_ops_per_second_single_threaded_churn() {
119 let counter: HyperCounter<i32, AtomicI32> = HyperCounter::new();
120
121 let now = Instant::now();
122 let mut i = 0;
123
124 loop {
125 if i % 2 == 0 {
126 counter.fetch_add(i, 1, Ordering::Relaxed);
127 } else {
128 counter.fetch_sub(i, 1, Ordering::Relaxed);
129 }
130
131 i += 1;
132
133 if now.elapsed().as_secs() >= 1 {
134 break;
135 }
136 }
137
138 println!("Single-threaded churn op/s: {}", pretty_int(i));
139}
140
141fn load_ops_per_second_multi_threaded_fetch_add_single_key() {
142 let counter: Arc<HyperCounter<i32, AtomicI32>> = Arc::new(HyperCounter::new());
143
144 let mut handles = vec![];
145
146 for _ in 0..THREADS {
147 let counter = counter.clone();
148
149 let handle = std::thread::spawn(move || {
150 let now = Instant::now();
151
152 loop {
153 counter.fetch_add(1, 1, Ordering::Relaxed);
154
155 if now.elapsed().as_secs() >= 1 {
156 break;
157 }
158 }
159 });
160
161 handles.push(handle);
162 }
163
164 for handle in handles {
165 handle.join().unwrap();
166 }
167
168 let i = counter.load(&1, Ordering::Relaxed);
169
170 println!("Multi-threaded single-key load ops/sec: {}", pretty_int(i));
171}
172
173fn load_ops_per_second_multi_threaded_fetch_add_multi_key() {
174 let counter: Arc<HyperCounter<i32, AtomicI32>> = Arc::new(HyperCounter::new());
175
176 let mut handles = vec![];
177
178 for thread_id in 0..THREADS {
179 let counter = counter.clone();
180
181 let handle = std::thread::spawn(move || {
182 let now = Instant::now();
183
184 for i in 0.. {
185 let key = (i + thread_id) % 1000;
186 counter.fetch_add(key, 1, Ordering::Relaxed);
187
188 if now.elapsed().as_secs() >= 1 {
189 break;
190 }
191 }
192 });
193
194 handles.push(handle);
195 }
196
197 for handle in handles {
198 handle.join().unwrap();
199 }
200
201 let mut i = 0;
202
203 for key in 0..1000 {
204 i += counter.load(&key, Ordering::Relaxed);
205 }
206
207 println!("Multi-threaded multi-key load ops/sec: {}", pretty_int(i));
208}
209
210fn load_ops_per_second_multi_threaded_insert() {
211 let counter: Arc<HyperCounter<i32, AtomicI32>> = Arc::new(HyperCounter::new());
212
213 let mut handles = vec![];
214
215 for thread_id in 0..THREADS {
216 let counter = counter.clone();
217
218 let handle = std::thread::spawn(move || {
219 let now = Instant::now();
220
221 for i in 0.. {
222 let key = i + thread_id * 1_000_000;
223 counter.fetch_add(key, 1, Ordering::Relaxed);
224
225 if now.elapsed().as_secs() >= 1 {
226 break;
227 }
228 }
229 });
230
231 handles.push(handle);
232 }
233
234 for handle in handles {
235 handle.join().unwrap();
236 }
237
238 let i = counter.len();
239
240 println!("Multi-threaded insert ops/sec: {}", pretty_int(i as i32));
241}
242
243fn load_ops_per_second_multi_threaded_remove() {
244 let counter: Arc<HyperCounter<i32, AtomicI32>> = Arc::new(HyperCounter::new());
245
246 for i in 0..8_000_000 {
247 counter.fetch_add(i, 1, Ordering::Relaxed);
248 }
249
250 let mut handles = vec![];
251
252 for thread_id in 0..THREADS {
253 let counter = counter.clone();
254
255 let handle = std::thread::spawn(move || {
256 let now = Instant::now();
257
258 for i in 0.. {
259 let key = i + thread_id * 1_000_000;
260 counter.fetch_sub(key, 1, Ordering::Relaxed);
261
262 if now.elapsed().as_secs() >= 1 {
263 break;
264 }
265 }
266 });
267
268 handles.push(handle);
269 }
270
271 for handle in handles {
272 handle.join().unwrap();
273 }
274
275 let i = counter.len();
276
277 println!(
278 "Multi-threaded remove ops/sec: {}",
279 pretty_int(8_000_000 - i as i32)
280 );
281}
282
283fn load_ops_per_second_multi_threaded_churn() {
284 let counter: Arc<HyperCounter<i32, AtomicI32>> = Arc::new(HyperCounter::new());
285
286 let mut handles = vec![];
287
288 for _ in 0..THREADS {
289 let counter = counter.clone();
290
291 let handle = std::thread::spawn(move || {
292 let now = Instant::now();
293 let mut i = 0;
294
295 loop {
296 if i % 2 == 0 {
297 counter.fetch_add(1, 1, Ordering::Relaxed);
298 } else {
299 counter.fetch_sub(1, 1, Ordering::Relaxed);
300 }
301
302 i += 1;
303
304 if now.elapsed().as_secs() >= 1 {
305 break;
306 }
307 }
308
309 i
310 });
311
312 handles.push(handle);
313 }
314
315 let mut i = 0;
316
317 for handle in handles {
318 i += handle.join().unwrap();
319 }
320
321 println!("Multi-threaded churn op/s: {}", pretty_int(i));
322}Sourcepub fn fetch_sub(
&self,
key: K,
value: V::Primitive,
ordering: Ordering,
) -> V::Primitive
pub fn fetch_sub( &self, key: K, value: V::Primitive, ordering: Ordering, ) -> V::Primitive
Atomically subtracts a value from the counter for the given key.
If the key ends up being zero after subtraction, the entry is removed.
If the key is missing, a new entry is created with zero - the given value.
Arguments:
key- The key to subtract from.value- The value to subtract.ordering- The memory ordering to use.
Returns:
- [
V::Primitive] - The previous value associated with the key. (before subtraction)
Examples found in repository?
96fn load_ops_per_second_single_threaded_remove() {
97 let counter: HyperCounter<i32, AtomicI32> = HyperCounter::new();
98
99 for i in 0..2_000_000 {
100 counter.fetch_add(i, 1, Ordering::Relaxed);
101 }
102
103 let now = Instant::now();
104 let mut i = 0;
105
106 loop {
107 counter.fetch_sub(i, 1, Ordering::Relaxed);
108 i += 1;
109
110 if now.elapsed().as_secs() >= 1 {
111 break;
112 }
113 }
114
115 println!("Single-threaded remove ops/sec: {}", pretty_int(i));
116}
117
118fn load_ops_per_second_single_threaded_churn() {
119 let counter: HyperCounter<i32, AtomicI32> = HyperCounter::new();
120
121 let now = Instant::now();
122 let mut i = 0;
123
124 loop {
125 if i % 2 == 0 {
126 counter.fetch_add(i, 1, Ordering::Relaxed);
127 } else {
128 counter.fetch_sub(i, 1, Ordering::Relaxed);
129 }
130
131 i += 1;
132
133 if now.elapsed().as_secs() >= 1 {
134 break;
135 }
136 }
137
138 println!("Single-threaded churn op/s: {}", pretty_int(i));
139}
140
141fn load_ops_per_second_multi_threaded_fetch_add_single_key() {
142 let counter: Arc<HyperCounter<i32, AtomicI32>> = Arc::new(HyperCounter::new());
143
144 let mut handles = vec![];
145
146 for _ in 0..THREADS {
147 let counter = counter.clone();
148
149 let handle = std::thread::spawn(move || {
150 let now = Instant::now();
151
152 loop {
153 counter.fetch_add(1, 1, Ordering::Relaxed);
154
155 if now.elapsed().as_secs() >= 1 {
156 break;
157 }
158 }
159 });
160
161 handles.push(handle);
162 }
163
164 for handle in handles {
165 handle.join().unwrap();
166 }
167
168 let i = counter.load(&1, Ordering::Relaxed);
169
170 println!("Multi-threaded single-key load ops/sec: {}", pretty_int(i));
171}
172
173fn load_ops_per_second_multi_threaded_fetch_add_multi_key() {
174 let counter: Arc<HyperCounter<i32, AtomicI32>> = Arc::new(HyperCounter::new());
175
176 let mut handles = vec![];
177
178 for thread_id in 0..THREADS {
179 let counter = counter.clone();
180
181 let handle = std::thread::spawn(move || {
182 let now = Instant::now();
183
184 for i in 0.. {
185 let key = (i + thread_id) % 1000;
186 counter.fetch_add(key, 1, Ordering::Relaxed);
187
188 if now.elapsed().as_secs() >= 1 {
189 break;
190 }
191 }
192 });
193
194 handles.push(handle);
195 }
196
197 for handle in handles {
198 handle.join().unwrap();
199 }
200
201 let mut i = 0;
202
203 for key in 0..1000 {
204 i += counter.load(&key, Ordering::Relaxed);
205 }
206
207 println!("Multi-threaded multi-key load ops/sec: {}", pretty_int(i));
208}
209
210fn load_ops_per_second_multi_threaded_insert() {
211 let counter: Arc<HyperCounter<i32, AtomicI32>> = Arc::new(HyperCounter::new());
212
213 let mut handles = vec![];
214
215 for thread_id in 0..THREADS {
216 let counter = counter.clone();
217
218 let handle = std::thread::spawn(move || {
219 let now = Instant::now();
220
221 for i in 0.. {
222 let key = i + thread_id * 1_000_000;
223 counter.fetch_add(key, 1, Ordering::Relaxed);
224
225 if now.elapsed().as_secs() >= 1 {
226 break;
227 }
228 }
229 });
230
231 handles.push(handle);
232 }
233
234 for handle in handles {
235 handle.join().unwrap();
236 }
237
238 let i = counter.len();
239
240 println!("Multi-threaded insert ops/sec: {}", pretty_int(i as i32));
241}
242
243fn load_ops_per_second_multi_threaded_remove() {
244 let counter: Arc<HyperCounter<i32, AtomicI32>> = Arc::new(HyperCounter::new());
245
246 for i in 0..8_000_000 {
247 counter.fetch_add(i, 1, Ordering::Relaxed);
248 }
249
250 let mut handles = vec![];
251
252 for thread_id in 0..THREADS {
253 let counter = counter.clone();
254
255 let handle = std::thread::spawn(move || {
256 let now = Instant::now();
257
258 for i in 0.. {
259 let key = i + thread_id * 1_000_000;
260 counter.fetch_sub(key, 1, Ordering::Relaxed);
261
262 if now.elapsed().as_secs() >= 1 {
263 break;
264 }
265 }
266 });
267
268 handles.push(handle);
269 }
270
271 for handle in handles {
272 handle.join().unwrap();
273 }
274
275 let i = counter.len();
276
277 println!(
278 "Multi-threaded remove ops/sec: {}",
279 pretty_int(8_000_000 - i as i32)
280 );
281}
282
283fn load_ops_per_second_multi_threaded_churn() {
284 let counter: Arc<HyperCounter<i32, AtomicI32>> = Arc::new(HyperCounter::new());
285
286 let mut handles = vec![];
287
288 for _ in 0..THREADS {
289 let counter = counter.clone();
290
291 let handle = std::thread::spawn(move || {
292 let now = Instant::now();
293 let mut i = 0;
294
295 loop {
296 if i % 2 == 0 {
297 counter.fetch_add(1, 1, Ordering::Relaxed);
298 } else {
299 counter.fetch_sub(1, 1, Ordering::Relaxed);
300 }
301
302 i += 1;
303
304 if now.elapsed().as_secs() >= 1 {
305 break;
306 }
307 }
308
309 i
310 });
311
312 handles.push(handle);
313 }
314
315 let mut i = 0;
316
317 for handle in handles {
318 i += handle.join().unwrap();
319 }
320
321 println!("Multi-threaded churn op/s: {}", pretty_int(i));
322}Sourcepub fn fetch_and(
&self,
key: &K,
value: V::Primitive,
ordering: Ordering,
) -> V::Primitive
pub fn fetch_and( &self, key: &K, value: V::Primitive, ordering: Ordering, ) -> V::Primitive
Atomically performs a bitwise AND operation on the counter for the given key.
If the key is missing, nothing is done and zero is returned.
Arguments:
key- The key to perform the AND operation on.value- The value to AND with.ordering- The memory ordering to use.
Returns:
- [
V::Primitive] - The previous value associated with the key. (before AND operation)
Sourcepub fn fetch_nand(
&self,
key: K,
value: V::Primitive,
ordering: Ordering,
) -> V::Primitive
pub fn fetch_nand( &self, key: K, value: V::Primitive, ordering: Ordering, ) -> V::Primitive
Atomically performs a bitwise NAND operation on the counter for the given key.
If the key is missing, the new value is inserted and all bits set (i.e., !0) is returned.
Arguments:
key- The key to perform the NAND operation on.value- The value to NAND with.ordering- The memory ordering to use.
Returns:
- [
V::Primitive] - The previous value associated with the key. (before NAND operation)
Sourcepub fn fetch_or(
&self,
key: K,
value: V::Primitive,
ordering: Ordering,
) -> V::Primitive
pub fn fetch_or( &self, key: K, value: V::Primitive, ordering: Ordering, ) -> V::Primitive
Atomically performs a bitwise OR operation on the counter for the given key.
If the key is missing, the new value is inserted and zero is returned.
Arguments:
key- The key to perform the OR operation on.value- The value to OR with.ordering- The memory ordering to use.
Returns:
- [
V::Primitive] - The previous value associated with the key. (before OR operation)
Sourcepub fn fetch_xor(
&self,
key: K,
value: V::Primitive,
ordering: Ordering,
) -> V::Primitive
pub fn fetch_xor( &self, key: K, value: V::Primitive, ordering: Ordering, ) -> V::Primitive
Atomically performs a bitwise XOR operation on the counter for the given key.
If the key is missing, the new value is inserted and zero is returned.
If the resulting value is zero after the XOR operation, the entry is removed.
Arguments:
key- The key to perform the XOR operation on.value- The value to XOR with.ordering- The memory ordering to use.
Returns:
- [
V::Primitive] - The previous value associated with the key. (before XOR operation)
Sourcepub fn fetch_max(
&self,
key: K,
value: V::Primitive,
ordering: Ordering,
) -> V::Primitive
pub fn fetch_max( &self, key: K, value: V::Primitive, ordering: Ordering, ) -> V::Primitive
Atomically sets the counter for the given key to the maximum of its current value and the given value.
If the key is missing and the value is higher than zero, the new value is inserted and zero is returned. Otherwise, nothing is done and zero is returned.
Arguments:
key- The key to perform the max operation on.value- The value to compare with.ordering- The memory ordering to use.
Returns:
- [
V::Primitive] - The previous value associated with the key. (before max operation)
Sourcepub fn fetch_min(
&self,
key: K,
value: V::Primitive,
ordering: Ordering,
) -> V::Primitive
pub fn fetch_min( &self, key: K, value: V::Primitive, ordering: Ordering, ) -> V::Primitive
Atomically sets the counter for the given key to the minimum of its current value and the given value.
If the key is missing and the value is lower than zero, the new value is inserted and zero is returned. Otherwise, nothing is done and zero is returned.
Arguments:
key- The key to perform the min operation on.value- The value to compare with.ordering- The memory ordering to use.
Returns:
- [
V::Primitive] - The previous value associated with the key. (before min operation)
Sourcepub fn clear(&self)
pub fn clear(&self)
Removes all entries in the HyperCounter.
Source§impl<K, V, H> HyperCounter<K, V, H>
impl<K, V, H> HyperCounter<K, V, H>
Sourcepub fn retain(
&self,
f: impl FnMut(&K, &V::Primitive) -> bool,
ordering_load: Ordering,
ordering_remove: Ordering,
)
pub fn retain( &self, f: impl FnMut(&K, &V::Primitive) -> bool, ordering_load: Ordering, ordering_remove: Ordering, )
Retains only the entries specified by the predicate function.
Arguments:
f- The predicate function to determine which entries to retain.ordering_load- The memory ordering to use when loading values.ordering_remove- The memory ordering to use when removing entries.