From e7853520506d246352e2b3ed669e0c514b75207a Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Eric=20Espi=C3=A9?=
Date: Wed, 27 Sep 2017 09:37:43 +0000
Subject: [PATCH] N.1065 Fix performance issues (caches added on query build)
SVN:trunk[4943]
---
core/dbobjectsearch.class.php | 29 ++++----
core/expressioncache.class.inc.php | 110 +++++++++++++++++++++++++++++
core/metamodel.class.php | 21 ++++--
core/oql/expression.class.inc.php | 23 +++---
4 files changed, 151 insertions(+), 32 deletions(-)
create mode 100644 core/expressioncache.class.inc.php
diff --git a/core/dbobjectsearch.class.php b/core/dbobjectsearch.class.php
index e69fc6c1b..a6d384fab 100644
--- a/core/dbobjectsearch.class.php
+++ b/core/dbobjectsearch.class.php
@@ -1,9 +1,9 @@
-
-
-/**
- * Define filters for a given class of objects (formerly named "filter")
- *
- * @copyright Copyright (C) 2010-2017 Combodo SARL
- * @license http://opensource.org/licenses/AGPL-3.0
- */
+//
// Dev hack for disabling the some query build optimizations (Folding/Merging)
define('ENABLE_OPT', true);
@@ -1623,9 +1616,9 @@ class DBObjectSearch extends DBSearch
$bIsOnQueriedClass = array_key_exists($sClassAlias, $oBuild->GetRootFilter()->GetSelectedClasses());
- self::DbgTrace("Entering: ".$this->ToOQL().", ".($bIsOnQueriedClass ? "MAIN" : "SECONDARY"));
+ //self::DbgTrace("Entering: ".$this->ToOQL().", ".($bIsOnQueriedClass ? "MAIN" : "SECONDARY"));
- $sRootClass = MetaModel::GetRootClass($sClass);
+ //$sRootClass = MetaModel::GetRootClass($sClass);
$sKeyField = MetaModel::DBGetKey($sClass);
if ($bIsOnQueriedClass)
@@ -1679,9 +1672,9 @@ class DBObjectSearch extends DBSearch
}
}
}
-//echo "oQBExpr ".__LINE__.":
\n".print_r($oBuild->m_oQBExpressions, true)."
\n";
+ //echo "oQBExpr ".__LINE__.":
\n".print_r($oBuild->m_oQBExpressions, true)."
\n";
$aExpectedAtts = array(); // array of (attcode => fieldexpression)
-//echo "".__LINE__.": GetUnresolvedFields($sClassAlias, ...)
\n";
+ //echo "".__LINE__.": GetUnresolvedFields($sClassAlias, ...)
\n";
$oBuild->m_oQBExpressions->GetUnresolvedFields($sClassAlias, $aExpectedAtts);
// Compute a clear view of required joins (from the current class)
@@ -2159,8 +2152,14 @@ class DBObjectSearch extends DBSearch
* Get the expression for the class and its subclasses (if finalclass = 'subclass' ...)
* Simplifies the final expression by grouping classes having the same expression
*/
- static protected function GetPolymorphicExpression($sClass, $sAttCode)
+ static public function GetPolymorphicExpression($sClass, $sAttCode)
{
+ $oExpression = ExpressionCache::GetCachedExpression($sClass, $sAttCode);
+ if (!empty($oExpression))
+ {
+ return $oExpression;
+ }
+
// 1st step - get all of the required expressions (instantiable classes)
// and group them using their OQL representation
//
diff --git a/core/expressioncache.class.inc.php b/core/expressioncache.class.inc.php
new file mode 100644
index 000000000..16731391f
--- /dev/null
+++ b/core/expressioncache.class.inc.php
@@ -0,0 +1,110 @@
+
+//
+
+class ExpressionCache
+{
+ static private $aCache = array();
+
+ static public function GetCachedExpression($sClass, $sAttCode)
+ {
+ // read current cache
+ @include_once (static::GetCacheFileName());
+
+ $oExpr = null;
+ $sKey = static::GetKey($sClass, $sAttCode);
+ if (array_key_exists($sKey, static::$aCache))
+ {
+ $oExpr = static::$aCache[$sKey];
+ }
+ else
+ {
+ if (class_exists('ExpressionCacheData'))
+ {
+ if (array_key_exists($sKey, ExpressionCacheData::$aCache))
+ {
+ $sVal = ExpressionCacheData::$aCache[$sKey];
+ $oExpr = unserialize($sVal);
+ static::$aCache[$sKey] = $oExpr;
+ }
+ }
+ }
+ return $oExpr;
+ }
+
+
+ static public function Warmup()
+ {
+ $sFilePath = static::GetCacheFileName();
+
+ if (!is_file($sFilePath))
+ {
+ $content = << '".serialize($oExpr)."',\n";
+ }
+
+ /**
+ * @param $sClass
+ * @param $sAttCode
+ * @return string
+ */
+ static private function GetKey($sClass, $sAttCode)
+ {
+ return $sClass.'::'.$sAttCode;
+ }
+
+ public static function GetCacheFileName()
+ {
+ return utils::GetCachePath().'expressioncache.php';
+ }
+
+}
+
+
+
diff --git a/core/metamodel.class.php b/core/metamodel.class.php
index 75b1a3934..42a4f3ffe 100644
--- a/core/metamodel.class.php
+++ b/core/metamodel.class.php
@@ -1,9 +1,9 @@
+//
require_once(APPROOT.'core/modulehandler.class.inc.php');
require_once(APPROOT.'core/querybuildercontext.class.inc.php');
@@ -23,6 +24,7 @@ require_once(APPROOT.'core/metamodelmodifier.inc.php');
require_once(APPROOT.'core/computing.inc.php');
require_once(APPROOT.'core/relationgraph.class.inc.php');
require_once(APPROOT.'core/apc-compat.php');
+require_once(APPROOT.'core/expressioncache.class.inc.php');
/**
* Metamodel
@@ -331,9 +333,16 @@ abstract class MetaModel
}
final static public function GetObsolescenceExpression($sClass)
{
- self::_check_subclass($sClass);
- $sOql = self::$m_aClassParams[$sClass]['obsolescence_expression'];
- $oRet = Expression::FromOQL("COALESCE($sOql, 0)");
+ if (self::IsObsoletable($sClass))
+ {
+ self::_check_subclass($sClass);
+ $sOql = self::$m_aClassParams[$sClass]['obsolescence_expression'];
+ $oRet = Expression::FromOQL("COALESCE($sOql, 0)");
+ }
+ else
+ {
+ $oRet = Expression::FromOQL("0");
+ }
return $oRet;
}
final static public function GetNameSpec($sClass)
@@ -4394,6 +4403,8 @@ abstract class MetaModel
echo "Debug
\n";
self::static_var_dump();
}
+
+ ExpressionCache::Warmup();
}
public static function LoadConfig($oConfiguration, $bAllowCache = false)
diff --git a/core/oql/expression.class.inc.php b/core/oql/expression.class.inc.php
index 20a11173d..1863fd6d1 100644
--- a/core/oql/expression.class.inc.php
+++ b/core/oql/expression.class.inc.php
@@ -1,9 +1,9 @@
+//
-
-/**
- * General definition of an expression tree (could be OQL, SQL or whatever)
- *
- * @copyright Copyright (C) 2010-2017 Combodo SARL
- * @license http://opensource.org/licenses/AGPL-3.0
- */
-
-class MissingQueryArgument extends CoreException
+lass MissingQueryArgument extends CoreException
{
}
@@ -89,9 +82,15 @@ abstract class Expression
*/
static public function FromOQL($sConditionExpr)
{
+ static $aCache = array();
+ if (array_key_exists($sConditionExpr, $aCache))
+ {
+ return $aCache[$sConditionExpr];
+ }
$oOql = new OqlInterpreter($sConditionExpr);
$oExpression = $oOql->ParseExpression();
-
+ $aCache[$sConditionExpr] = $oExpression;
+
return $oExpression;
}