Cache applicable entity search for a given filter
We have a large number (thousands) of individual unique code discounts which all apply to the same event type. This causes a huge performance issue because any time an event registration page is loaded, all events of this type are searched by checkDiscountsByEntity() which is called for every single discount. Fortunately, this is easily solved by adding a cache to checkDiscountsByEntity() in DiscountCalculator.php, for example:
7 protected static $filterSearchCache = array();
...
176 if (count($discount[$type][$entity]) == 1 && CRM_Utils_Array::value('id', $discount[$type][$entity])) {
177 // If this discount is only limited by specific entity (say, a specific
178 // event and not an event type), we have the IDs already and don't need
179 // to make an API call. Store the IDs in a structure like they would
180 // have as the result of an API call.
181 $ids = ['values' => array_flip($discount[$type][$entity]['id']['IN'])];
182 }
183 else {
184 $cache_key = $type . "-" . $entity . "-" . json_encode($discount[$type][$entity]);
185
186 if (!array_key_exists($cache_key, CRM_CiviDiscount_DiscountCalculator::$filterSearchCache)) {
187 $params = $discount[$type][$entity] + array_merge([
188 'options' => ['limit' => 999999999],
189 'return' => 'id',
190 ], $additionalFilter);
191 $filter_result = civicrm_api3($entity, 'get', $params);
192 CRM_CiviDiscount_DiscountCalculator::$filterSearchCache[$cache_key] = $filter_result;
193 }
194 $ids = CRM_CiviDiscount_DiscountCalculator::$filterSearchCache[$cache_key];
Not directly relevant notes: After implementing this cache I was still having significant performance problems but this turned out to be related to watchdog logging. Any notice message generated was being logged to the DB once per discount (thousands of discounts, thousands of DB inserts). I went through and fixed all the notices - but they could easily come back with any extension update. I think I may end up forking and hard-coding these discount types and bypass the filter system for some types of discounts.