From b74d4d5cd30fc5fb8cc6c9f7b4e1d648de251fe1 Mon Sep 17 00:00:00 2001 From: Coleman Watts Date: Sat, 23 Oct 2021 19:27:21 -0400 Subject: [PATCH] APIv4 - Fix performance drag caused by getInfoItem calling the API This function is sometimes called thousands of times per request, e.g. for every cell in a searchKit display table. Going through the API wrapper that many times is a considerable (+10 sec) drag on performance. Instead of calling Entity.get, we can just read directly from the cache where it stores its data. --- Civi/Api4/Utils/CoreUtil.php | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/Civi/Api4/Utils/CoreUtil.php b/Civi/Api4/Utils/CoreUtil.php index 62ee8124d9..fdf1ad6668 100644 --- a/Civi/Api4/Utils/CoreUtil.php +++ b/Civi/Api4/Utils/CoreUtil.php @@ -45,17 +45,26 @@ class CoreUtil { } /** - * Get item from an entity's getInfo array + * Get a piece of metadata about an entity * * @param string $entityName * @param string $keyToReturn * @return mixed */ public static function getInfoItem(string $entityName, string $keyToReturn) { - $info = Entity::get(FALSE) - ->addWhere('name', '=', $entityName) - ->addSelect($keyToReturn) - ->execute()->first(); + // Because this function might be called thousands of times per request, read directly + // from the cache set by Apiv4 Entity.get to avoid the processing overhead of the API wrapper. + $cached = \Civi::cache('metadata')->get('api4.entities.info'); + if ($cached) { + $info = $cached[$entityName] ?? NULL; + } + // If the cache is empty, calling Entity.get will populate it and we'll use it next time. + else { + $info = Entity::get(FALSE) + ->addWhere('name', '=', $entityName) + ->addSelect($keyToReturn) + ->execute()->first(); + } return $info ? $info[$keyToReturn] ?? NULL : NULL; } -- 2.25.1