Quantcast

Use lazy evaluation to reduce the number of times the script is compiled.

Johnny C. Lam [05-12-14 - 16:08]
Use lazy evaluation to reduce the number of times the script is compiled.

git-svn-id: svn://svn.curseforge.net/wow/ovale/mainline/trunk@1425 d5049fe3-3747-40f7-a4b5-f36d6801af5f
Filename
OvaleCompile.lua
OvaleFrame.lua
diff --git a/OvaleCompile.lua b/OvaleCompile.lua
index f8142ed..4b580cc 100644
--- a/OvaleCompile.lua
+++ b/OvaleCompile.lua
@@ -56,6 +56,11 @@ local self_functionCalls = {}
 local self_compileOnItems = false
 local self_compileOnStances = false

+-- Current age of compilation state.
+local self_serial = 0
+-- Master nodes of the current script (one node for each icon)
+local self_masterNodes = {}
+
 -- Lua pattern to match a key=value pair, returning key and value.
 local KEY_VALUE_PATTERN = "([%w_]+)=(!?[-%w\\_%.]+)"
 -- Lua pattern to match a floating-point number that may start with a minus sign.
@@ -90,8 +95,8 @@ local OVALE_FUNCTIONS = {
 --</private-static-properties>

 --<public-static-properties>
---master nodes of the current script (one node for each icon)
-OvaleCompile.masterNodes = {}
+-- Current age of the current compiled script.
+OvaleCompile.serial = nil
 OvaleCompile.customFunctionNode = {}
 --</public-static-properties>

@@ -829,21 +834,20 @@ local function CompileScript(text)
 		end
 	end

-	local masterNodes = OvaleCompile.masterNodes
-	wipe(masterNodes)
-
 	-- On compile les AddIcon
+	wipe(self_masterNodes)
+
 	for p,t in strgmatch(text, "AddActionIcon%s*(.-)%s*(%b{})") do
 		local node = ParseAddIcon(p,t,true)
 		if node then
-			tinsert(masterNodes, node)
+			tinsert(self_masterNodes, node)
 		end
 	end

 	for p,t in strgmatch(text, "AddIcon%s*(.-)%s*(%b{})") do
 		local node = ParseAddIcon(p,t)
 		if node then
-			tinsert(masterNodes, node)
+			tinsert(self_masterNodes, node)
 		end
 	end

@@ -917,7 +921,9 @@ end

 function OvaleCompile:EventHandler(event)
 	Ovale:DebugPrint(OVALE_COMPILE_DEBUG, event)
-	self:Compile()
+	-- Advance age of current compilation state.
+	self_serial = self_serial + 1
+	Ovale.refreshNeeded["player"] = true
 end

 function OvaleCompile:Compile()
@@ -930,13 +936,21 @@ function OvaleCompile:Compile()
 		code = ""
 	end
 	CompileScript(code)
-	Ovale.refreshNeeded.player = true
 	Ovale:UpdateFrame()
 end

+function OvaleCompile:GetMasterNodes()
+	-- Compile the script if it is outdated.
+	if not self.serial or self.serial < self_serial then
+		self.serial = self_serial
+		self:Compile()
+	end
+	return self_masterNodes
+end
+
 function OvaleCompile:Debug()
 	self_pool:Debug()
-	Ovale:Print(self:DebugNode(self.masterNodes[1]))
+	Ovale:Print(self:DebugNode(self_masterNodes[1]))
 end

 function OvaleCompile:DebugNode(node)
diff --git a/OvaleFrame.lua b/OvaleFrame.lua
index a0287de..ccc0740 100644
--- a/OvaleFrame.lua
+++ b/OvaleFrame.lua
@@ -165,18 +165,20 @@ do
 		local now = API_GetTime()

 		local profile = OvaleOptions:GetProfile()
+		-- Force a refresh if we've exceeded the minimum update interval since the last refresh.
 		local forceRefresh = not self.lastUpdate or (now > self.lastUpdate + profile.apparence.updateInterval)
-
-		if not next(Ovale.refreshNeeded) and not forceRefresh then
-			return
-		end
-		if not OvaleCompile.masterNodes then return end
+		-- Refresh the icons if we're forcing a refresh or if one of the units the script is tracking needs a refresh.
+		local refresh = forceRefresh or next(Ovale.refreshNeeded)
+		if not refresh then return end
+
+		local masterNodes = OvaleCompile:GetMasterNodes()
+		if not masterNodes then return end

 		self.lastUpdate = now

 		local state = OvaleState.state
 		state:Initialize()
-		for k,node in pairs(OvaleCompile.masterNodes) do
+		for k,node in pairs(masterNodes) do
 			local target
 			if node.params and node.params.target then
 				target = node.params.target
@@ -185,7 +187,7 @@ do
 			end
 			OvaleCondition.defaultTarget = target

-			if forceRefresh or Ovale.refreshNeeded[target] or Ovale.refreshNeeded["player"] or Ovale.refreshNeeded["pet"] then
+			if refresh then
 				Ovale:Logf("****Master Node %d", k)
 				OvaleBestAction:StartNewAction(state)
 				local timeSpan, _, element = OvaleBestAction:Compute(node, state)
@@ -194,12 +196,7 @@ do
 					Ovale:Logf("Compute start = %f", start)
 				end
 				local action = self.actions[k]
-				local icons
-				if action.secure then
-					icons = action.secureIcons
-				else
-					icons = action.icons
-				end
+				local icons = action.secure and action.secureIcons or action.icons
 				if element and element.type == "value" then
 					local actionTexture
 					if node.params and node.params.texture then
@@ -315,16 +312,15 @@ do
 		local maxHeight = 0
 		local maxWidth = 0
 		local top = 0
-
-		if (not OvaleCompile.masterNodes) then
-			return;
-		end
+
+		local masterNodes = OvaleCompile:GetMasterNodes()
+		if not masterNodes then return end

 		local BARRE = 8

 		local margin = profile.apparence.margin

-		for k,node in pairs(OvaleCompile.masterNodes) do
+		for k,node in pairs(masterNodes) do
 			if not self.actions[k] then
 				self.actions[k] = {icons={}, secureIcons={}}
 			end