From: Vsevolod Stakhov Date: Wed, 26 Nov 2025 12:33:26 +0000 (+0000) Subject: [Feature] Precompute composite atom types at config time X-Git-Tag: 3.14.1~5^2~2 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=c2223354344cd213e119e4a2a16109772954f147;p=thirdparty%2Frspamd.git [Feature] Precompute composite atom types at config time Resolve ATOM_COMPOSITE vs ATOM_PLAIN for all composite atoms during configuration phase instead of lazy evaluation at runtime. This eliminates repeated hash lookups during expression evaluation. - Add rspamd_composites_resolve_atom_types() function - Call after process_dependencies() and before build_inverted_index() - Sets comp_type and ncomp pointer for each atom upfront --- diff --git a/src/libserver/composites/composites.cxx b/src/libserver/composites/composites.cxx index b9ab013da2..dccd15cb8d 100644 --- a/src/libserver/composites/composites.cxx +++ b/src/libserver/composites/composites.cxx @@ -1043,6 +1043,43 @@ composites_metric_callback(struct rspamd_task *task) } } +void rspamd_composites_resolve_atom_types(composites_manager *cm) +{ + auto resolve_callback = [](GNode *, rspamd_expression_atom_t *atom, gpointer ud) { + auto *manager = reinterpret_cast(ud); + auto *comp_atom = reinterpret_cast(atom->data); + + if (comp_atom == nullptr) { + return; + } + + if (comp_atom->comp_type != rspamd_composite_atom_type::ATOM_UNKNOWN) { + /* Already resolved */ + return; + } + + const auto *ncomp = manager->find(comp_atom->symbol); + if (ncomp != nullptr) { + comp_atom->comp_type = rspamd_composite_atom_type::ATOM_COMPOSITE; + comp_atom->ncomp = ncomp; + } + else { + comp_atom->comp_type = rspamd_composite_atom_type::ATOM_PLAIN; + comp_atom->ncomp = nullptr; + } + }; + + /* Process all first-pass composites */ + for (auto *comp: cm->first_pass_composites) { + rspamd_expression_atom_foreach_ex(comp->expr, resolve_callback, cm); + } + + /* Process all second-pass composites */ + for (auto *comp: cm->second_pass_composites) { + rspamd_expression_atom_foreach_ex(comp->expr, resolve_callback, cm); + } +} + }// namespace rspamd::composites diff --git a/src/libserver/composites/composites_internal.hxx b/src/libserver/composites/composites_internal.hxx index 032747e872..8cce77f267 100644 --- a/src/libserver/composites/composites_internal.hxx +++ b/src/libserver/composites/composites_internal.hxx @@ -128,6 +128,13 @@ public: void build_inverted_index(); }; +/** + * Precompute atom types (ATOM_COMPOSITE vs ATOM_PLAIN) for all composites. + * This eliminates lazy lookups during expression evaluation. + * Should be called after all composites are registered. + */ +void rspamd_composites_resolve_atom_types(composites_manager *cm); + }// namespace rspamd::composites #endif//RSPAMD_COMPOSITES_INTERNAL_HXX diff --git a/src/libserver/composites/composites_manager.cxx b/src/libserver/composites/composites_manager.cxx index 0f75e691e0..df09cea156 100644 --- a/src/libserver/composites/composites_manager.cxx +++ b/src/libserver/composites/composites_manager.cxx @@ -611,5 +611,6 @@ void rspamd_composites_process_deps(void *cm_ptr, struct rspamd_config *cfg) { auto *cm = COMPOSITE_MANAGER_FROM_PTR(cm_ptr); cm->process_dependencies(); + rspamd_composites_resolve_atom_types(cm); cm->build_inverted_index(); } \ No newline at end of file