}
}
+void rspamd_mempool_entries_foreach(rspamd_mempool_entry_cb cb, void *ud)
+{
+ khiter_t k;
+
+ if (cb == NULL || mempool_entries == NULL) {
+ return;
+ }
+
+ for (k = kh_begin(mempool_entries); k != kh_end(mempool_entries); ++k) {
+ if (!kh_exist(mempool_entries, k)) {
+ continue;
+ }
+
+ struct rspamd_mempool_entry_point *elt = kh_value(mempool_entries, k);
+ rspamd_mempool_entry_stat_t st;
+ uint64_t sum_frag = 0;
+ uint64_t sum_left = 0;
+ unsigned int valid = 0;
+
+ for (unsigned int i = 0; i < G_N_ELEMENTS(elt->elts); i++) {
+ if (elt->elts[i].fragmentation != 0 || elt->elts[i].leftover != 0) {
+ sum_frag += elt->elts[i].fragmentation;
+ sum_left += elt->elts[i].leftover;
+ valid++;
+ }
+ }
+
+ st.src = elt->src;
+ st.cur_suggestion = elt->cur_suggestion;
+ st.cur_elts = elt->cur_elts;
+ st.cur_vars = elt->cur_vars;
+ st.cur_dtors = elt->cur_dtors;
+ st.samples = valid;
+ st.avg_fragmentation = valid ? (uint32_t) (sum_frag / valid) : 0;
+ st.avg_leftover = valid ? (uint32_t) (sum_left / valid) : 0;
+
+ cb(&st, ud);
+ }
+}
+
gsize rspamd_mempool_suggest_size_(const char *loc)
{
return 0;
*/
void rspamd_mempool_stat_reset(void);
+/**
+ * Per-callsite mempool statistics, aggregated from the rolling history
+ */
+typedef struct rspamd_mempool_entry_stat_s {
+ const char *src; /**< callsite location string (file:line) */
+ uint32_t cur_suggestion; /**< current suggested pool size */
+ uint32_t cur_elts; /**< suggested number of preallocated elts */
+ uint32_t cur_vars; /**< suggested number of preallocated vars */
+ uint32_t cur_dtors; /**< suggested number of preallocated dtors */
+ uint32_t avg_fragmentation; /**< average fragmentation across history */
+ uint32_t avg_leftover; /**< average leftover across history */
+ uint32_t samples; /**< number of valid samples used for averages */
+} rspamd_mempool_entry_stat_t;
+
+typedef void (*rspamd_mempool_entry_cb)(const rspamd_mempool_entry_stat_t *stat,
+ void *ud);
+
+/**
+ * Iterate over all currently registered mempool callsite entries.
+ * The callback is invoked synchronously for each entry; the rspamd_mempool_entry_stat_t
+ * pointer and its src field are valid only for the duration of the callback.
+ */
+void rspamd_mempool_entries_foreach(rspamd_mempool_entry_cb cb, void *ud);
+
/**
* Get optimal pool size based on page size for this system
* @return size of memory page in system