master
h 234 lines 9.52 KB
Raw
1 // SPDX-License-Identifier: GPL-3.0-or-later
2
3 #ifndef NETDATA_DICTIONARY_STATISTICS_H
4 #define NETDATA_DICTIONARY_STATISTICS_H
5
6 #include "dictionary-internals.h"
7
8 // ----------------------------------------------------------------------------
9 // memory statistics
10
11 #ifdef DICT_WITH_STATS
12 static inline void DICTIONARY_STATS_PLUS_MEMORY(DICTIONARY *dict, size_t key_size __maybe_unused, size_t item_size, size_t value_size) {
13 if(item_size)
14 __atomic_fetch_add(&dict->stats->memory.dict, (long)item_size, __ATOMIC_RELAXED);
15
16 if(value_size)
17 __atomic_fetch_add(&dict->stats->memory.values, (long)value_size, __ATOMIC_RELAXED);
18 }
19
20 static inline void DICTIONARY_STATS_MINUS_MEMORY(DICTIONARY *dict, size_t key_size __maybe_unused, size_t item_size, size_t value_size) {
21 if(item_size)
22 __atomic_fetch_sub(&dict->stats->memory.dict, (long)item_size, __ATOMIC_RELAXED);
23
24 if(value_size)
25 __atomic_fetch_sub(&dict->stats->memory.values, (long)value_size, __ATOMIC_RELAXED);
26 }
27 #else
28 #define DICTIONARY_STATS_PLUS_MEMORY(dict, key_size, item_size, value_size) do {(void)item_size;} while(0)
29 #define DICTIONARY_STATS_MINUS_MEMORY(dict, key_size, item_size, value_size) do {;} while(0)
30 #endif
31
32 // ----------------------------------------------------------------------------
33 // internal statistics API
34
35 #ifdef DICT_WITH_STATS
36 static inline void DICTIONARY_STATS_SEARCHES_PLUS1(DICTIONARY *dict) {
37 __atomic_fetch_add(&dict->stats->ops.searches, 1, __ATOMIC_RELAXED);
38 }
39 #else
40 #define DICTIONARY_STATS_SEARCHES_PLUS1(dict) do {;} while(0)
41 #endif
42
43 static inline void DICTIONARY_ENTRIES_PLUS1(DICTIONARY *dict) {
44 #ifdef DICT_WITH_STATS
45 // statistics
46 __atomic_fetch_add(&dict->stats->items.entries, 1, __ATOMIC_RELAXED);
47 __atomic_fetch_add(&dict->stats->items.referenced, 1, __ATOMIC_RELAXED);
48 __atomic_fetch_add(&dict->stats->ops.inserts, 1, __ATOMIC_RELAXED);
49 #endif
50
51 if(unlikely(is_dictionary_single_threaded(dict))) {
52 dict->version++;
53 dict->entries++;
54 dict->referenced_items++;
55
56 }
57 else {
58 __atomic_fetch_add(&dict->version, 1, __ATOMIC_RELAXED);
59 __atomic_fetch_add(&dict->entries, 1, __ATOMIC_RELAXED);
60 __atomic_fetch_add(&dict->referenced_items, 1, __ATOMIC_RELAXED);
61 }
62 }
63
64 static inline void DICTIONARY_ENTRIES_MINUS1(DICTIONARY *dict) {
65 #ifdef DICT_WITH_STATS
66 // statistics
67 __atomic_fetch_add(&dict->stats->ops.deletes, 1, __ATOMIC_RELAXED);
68 __atomic_fetch_sub(&dict->stats->items.entries, 1, __ATOMIC_RELAXED);
69 #endif
70
71 size_t entries; (void)entries;
72 if(unlikely(is_dictionary_single_threaded(dict))) {
73 dict->version++;
74 entries = dict->entries--;
75 }
76 else {
77 __atomic_fetch_add(&dict->version, 1, __ATOMIC_RELAXED);
78 entries = __atomic_fetch_sub(&dict->entries, 1, __ATOMIC_RELAXED);
79 }
80
81 dictionary_internal_fatal(entries == 0, dict,
82 "DICT: negative number of entries in dictionary");
83 }
84
85 static inline void DICTIONARY_VALUE_RESETS_PLUS1(DICTIONARY *dict) {
86 #ifdef DICT_WITH_STATS
87 __atomic_fetch_add(&dict->stats->ops.resets, 1, __ATOMIC_RELAXED);
88 #endif
89
90 if(unlikely(is_dictionary_single_threaded(dict)))
91 dict->version++;
92 else
93 __atomic_fetch_add(&dict->version, 1, __ATOMIC_RELAXED);
94 }
95
96 #ifdef DICT_WITH_STATS
97 static inline void DICTIONARY_STATS_TRAVERSALS_PLUS1(DICTIONARY *dict) {
98 __atomic_fetch_add(&dict->stats->ops.traversals, 1, __ATOMIC_RELAXED);
99 }
100 static inline void DICTIONARY_STATS_WALKTHROUGHS_PLUS1(DICTIONARY *dict) {
101 __atomic_fetch_add(&dict->stats->ops.walkthroughs, 1, __ATOMIC_RELAXED);
102 }
103 static inline void DICTIONARY_STATS_CHECK_SPINS_PLUS(DICTIONARY *dict, size_t count) {
104 __atomic_fetch_add(&dict->stats->spin_locks.use_spins, count, __ATOMIC_RELAXED);
105 }
106 static inline void DICTIONARY_STATS_INSERT_SPINS_PLUS(DICTIONARY *dict, size_t count) {
107 __atomic_fetch_add(&dict->stats->spin_locks.insert_spins, count, __ATOMIC_RELAXED);
108 }
109 static inline void DICTIONARY_STATS_DELETE_SPINS_PLUS(DICTIONARY *dict, size_t count) {
110 __atomic_fetch_add(&dict->stats->spin_locks.delete_spins, count, __ATOMIC_RELAXED);
111 }
112 static inline void DICTIONARY_STATS_SEARCH_IGNORES_PLUS1(DICTIONARY *dict) {
113 __atomic_fetch_add(&dict->stats->spin_locks.search_spins, 1, __ATOMIC_RELAXED);
114 }
115 static inline void DICTIONARY_STATS_CALLBACK_INSERTS_PLUS1(DICTIONARY *dict) {
116 __atomic_fetch_add(&dict->stats->callbacks.inserts, 1, __ATOMIC_RELEASE);
117 }
118 static inline void DICTIONARY_STATS_CALLBACK_CONFLICTS_PLUS1(DICTIONARY *dict) {
119 __atomic_fetch_add(&dict->stats->callbacks.conflicts, 1, __ATOMIC_RELEASE);
120 }
121 static inline void DICTIONARY_STATS_CALLBACK_REACTS_PLUS1(DICTIONARY *dict) {
122 __atomic_fetch_add(&dict->stats->callbacks.reacts, 1, __ATOMIC_RELEASE);
123 }
124 static inline void DICTIONARY_STATS_CALLBACK_DELETES_PLUS1(DICTIONARY *dict) {
125 __atomic_fetch_add(&dict->stats->callbacks.deletes, 1, __ATOMIC_RELEASE);
126 }
127 static inline void DICTIONARY_STATS_GARBAGE_COLLECTIONS_PLUS1(DICTIONARY *dict) {
128 __atomic_fetch_add(&dict->stats->ops.garbage_collections, 1, __ATOMIC_RELAXED);
129 }
130 static inline void DICTIONARY_STATS_DICT_CREATIONS_PLUS1(DICTIONARY *dict) {
131 __atomic_fetch_add(&dict->stats->dictionaries.active, 1, __ATOMIC_RELAXED);
132 __atomic_fetch_add(&dict->stats->ops.creations, 1, __ATOMIC_RELAXED);
133 }
134 static inline void DICTIONARY_STATS_DICT_DESTRUCTIONS_PLUS1(DICTIONARY *dict) {
135 __atomic_fetch_sub(&dict->stats->dictionaries.active, 1, __ATOMIC_RELAXED);
136 __atomic_fetch_add(&dict->stats->ops.destructions, 1, __ATOMIC_RELAXED);
137 }
138 static inline void DICTIONARY_STATS_DICT_DESTROY_QUEUED_PLUS1(DICTIONARY *dict) {
139 __atomic_fetch_add(&dict->stats->dictionaries.deleted, 1, __ATOMIC_RELAXED);
140 }
141 static inline void DICTIONARY_STATS_DICT_DESTROY_QUEUED_MINUS1(DICTIONARY *dict) {
142 __atomic_fetch_sub(&dict->stats->dictionaries.deleted, 1, __ATOMIC_RELAXED);
143 }
144 static inline void DICTIONARY_STATS_DICT_FLUSHES_PLUS1(DICTIONARY *dict) {
145 __atomic_fetch_add(&dict->stats->ops.flushes, 1, __ATOMIC_RELAXED);
146 }
147 #else
148 #define DICTIONARY_STATS_TRAVERSALS_PLUS1(dict) do {;} while(0)
149 #define DICTIONARY_STATS_WALKTHROUGHS_PLUS1(dict) do {;} while(0)
150 #define DICTIONARY_STATS_CHECK_SPINS_PLUS(dict, count) do {;} while(0)
151 #define DICTIONARY_STATS_INSERT_SPINS_PLUS(dict, count) do {;} while(0)
152 #define DICTIONARY_STATS_DELETE_SPINS_PLUS(dict, count) do {;} while(0)
153 #define DICTIONARY_STATS_SEARCH_IGNORES_PLUS1(dict) do {;} while(0)
154 #define DICTIONARY_STATS_CALLBACK_INSERTS_PLUS1(dict) do {;} while(0)
155 #define DICTIONARY_STATS_CALLBACK_CONFLICTS_PLUS1(dict) do {;} while(0)
156 #define DICTIONARY_STATS_CALLBACK_REACTS_PLUS1(dict) do {;} while(0)
157 #define DICTIONARY_STATS_CALLBACK_DELETES_PLUS1(dict) do {;} while(0)
158 #define DICTIONARY_STATS_GARBAGE_COLLECTIONS_PLUS1(dict) do {;} while(0)
159 #define DICTIONARY_STATS_DICT_CREATIONS_PLUS1(dict) do {;} while(0)
160 #define DICTIONARY_STATS_DICT_DESTRUCTIONS_PLUS1(dict) do {;} while(0)
161 #define DICTIONARY_STATS_DICT_DESTROY_QUEUED_PLUS1(dict) do {;} while(0)
162 #define DICTIONARY_STATS_DICT_DESTROY_QUEUED_MINUS1(dict) do {;} while(0)
163 #define DICTIONARY_STATS_DICT_FLUSHES_PLUS1(dict) do {;} while(0)
164 #endif
165
166 static inline void DICTIONARY_REFERENCED_ITEMS_PLUS1(DICTIONARY *dict) {
167 #ifdef DICT_WITH_STATS
168 __atomic_fetch_add(&dict->stats->items.referenced, 1, __ATOMIC_RELAXED);
169 #endif
170
171 if(unlikely(is_dictionary_single_threaded(dict)))
172 ++dict->referenced_items;
173 else
174 __atomic_add_fetch(&dict->referenced_items, 1, __ATOMIC_RELAXED);
175 }
176
177 static inline void DICTIONARY_REFERENCED_ITEMS_MINUS1(DICTIONARY *dict) {
178 #ifdef DICT_WITH_STATS
179 __atomic_fetch_sub(&dict->stats->items.referenced, 1, __ATOMIC_RELAXED);
180 #endif
181
182 long int referenced_items; (void)referenced_items;
183 if(unlikely(is_dictionary_single_threaded(dict)))
184 referenced_items = --dict->referenced_items;
185 else
186 referenced_items = __atomic_sub_fetch(&dict->referenced_items, 1, __ATOMIC_SEQ_CST);
187
188 dictionary_internal_fatal(referenced_items < 0, dict,
189 "DICT: negative number of referenced items (%ld) in dictionary",
190 referenced_items);
191 }
192
193 static inline void DICTIONARY_PENDING_DELETES_PLUS1(DICTIONARY *dict) {
194 #ifdef DICT_WITH_STATS
195 __atomic_fetch_add(&dict->stats->items.pending_deletion, 1, __ATOMIC_RELAXED);
196 #endif
197
198 if(unlikely(is_dictionary_single_threaded(dict)))
199 ++dict->pending_deletion_items;
200 else
201 __atomic_add_fetch(&dict->pending_deletion_items, 1, __ATOMIC_RELEASE);
202 }
203
204 static inline long int DICTIONARY_PENDING_DELETES_MINUS1(DICTIONARY *dict) {
205 #ifdef DICT_WITH_STATS
206 __atomic_fetch_sub(&dict->stats->items.pending_deletion, 1, __ATOMIC_RELEASE);
207 #endif
208
209 if(unlikely(is_dictionary_single_threaded(dict)))
210 return --dict->pending_deletion_items;
211 else
212 return __atomic_sub_fetch(&dict->pending_deletion_items, 1, __ATOMIC_ACQUIRE);
213 }
214
215 static inline long int DICTIONARY_PENDING_DELETES_GET(DICTIONARY *dict) {
216 if(unlikely(is_dictionary_single_threaded(dict)))
217 return dict->pending_deletion_items;
218 else
219 return __atomic_load_n(&dict->pending_deletion_items, __ATOMIC_SEQ_CST);
220 }
221
222 static inline REFCOUNT DICTIONARY_ITEM_REFCOUNT_GET(DICTIONARY *dict, DICTIONARY_ITEM *item) {
223 if(unlikely(dict && is_dictionary_single_threaded(dict))) // this is an exception, dict can be null
224 return item->refcount;
225 else
226 return (REFCOUNT)__atomic_load_n(&item->refcount, __ATOMIC_ACQUIRE);
227 }
228
229 static inline REFCOUNT DICTIONARY_ITEM_REFCOUNT_GET_SOLE(DICTIONARY_ITEM *item) {
230 return (REFCOUNT)__atomic_load_n(&item->refcount, __ATOMIC_ACQUIRE);
231 }
232
233
234 #endif //NETDATA_DICTIONARY_STATISTICS_H