It is strange to see cache_reduce_memory itself consumes a lot of CPU. It doesn't contain CPU hungry code. It calls prepare_probe_slot, that calls some tuple forming. Then it calls resultcache_lookup that may call to ResultCacheHash_hash and ResultCacheHash_equal. And finally it calls remove_cache_entry. I suppose remove_cache_entry should consume most of CPU time since it does deallocations. And if you compile with --enable-cassert, then remove_cache_entry iterates through whole cache hashtable, therefore it reaches quadratic complexity easily (or more correct M*N, where M - size of a table, N - eviction count).