commit df7b7bf64eb354114e6c519e3e03ffc446afa8ba Author: Nathan Scott Date: Fri Nov 26 09:17:23 2021 +1100 libpcp_pmda: add indom cache fast-paths for inst lookup beyond max We encountered a situation where indom cache loading consumed vast CPU resources for an indom of size ~150k instances. Profiling was used to identify the insert loop that ensures the inst linked list within the cache hash tables is sorted - this loop is O(N*2) as we potentially walk this list from the start on every insert during a cache load. Because cache loading happens from a sorted file, the worst-case scenario happened every time - each new instance insert occurs beyond the current maximum. Fortunately we maintain a last entry pointer, so the new fast path uses that first and falls back to the original behaviour for an out-of-order insertion. A second opportunity for the same optimization was identified when auditing the rest of cache.c - in the find_inst() routine for inst identifier lookups beyond the current maximum observed instance. Resolves Red Hat BZ #2024648 diff --git a/src/libpcp_pmda/src/cache.c b/src/libpcp_pmda/src/cache.c index 0e66506d74..196ffc1da9 100644 --- a/src/libpcp_pmda/src/cache.c +++ b/src/libpcp_pmda/src/cache.c @@ -328,6 +328,9 @@ find_inst(hdr_t *h, int inst) { entry_t *e; + if ((e = h->last) != NULL && e->inst < inst) + return NULL; + for (e = h->first; e != NULL; e = e->next) { if (e->inst == inst && e->state != PMDA_CACHE_EMPTY) break; @@ -621,7 +624,11 @@ insert_cache(hdr_t *h, const char *name, int inst, int *sts) *sts = PM_ERR_INST; return e; } - for (e = h->first; e != NULL; e = e->next) { + /* if this entry is beyond the (sorted) list end, avoid linear scan */ + if ((e = h->last) == NULL || e->inst > inst) + e = h->first; + /* linear search over linked list, starting at either first or last */ + for (; e != NULL; e = e->next) { if (e->inst < inst) last_e = e; else if (e->inst > inst)