Implement cache clear reasons to avoid clearing caches when we do not need that (esp useful for dmg time cache)

This commit is contained in:
DarkPhoenix
2019-07-07 02:08:04 +03:00
parent 5bba1dc88b
commit 3e410540c9
6 changed files with 67 additions and 35 deletions

View File

@@ -21,6 +21,8 @@
from abc import ABCMeta, abstractmethod
from collections import OrderedDict, namedtuple
from service.const import GraphCacheCleanupReason
YDef = namedtuple('YDef', ('handle', 'unit', 'label'))
XDef = namedtuple('XDef', ('handle', 'unit', 'label', 'mainInput'))
@@ -92,24 +94,26 @@ class FitGraph(metaclass=ABCMeta):
self._plotCache.setdefault(cacheKey, {})[(ySpec, xSpec)] = plotData
return plotData
def clearCache(self, fitID=None):
# Clear everything
if fitID is None:
def clearCache(self, reason, extraData=None):
# If only one fit changed - clear plots which concern this fit
if reason == GraphCacheCleanupReason.fitChanged:
# Clear plot cache
plotKeysToClear = set()
for cacheKey in self._plotCache:
cacheFitID, cacheTgtType, cacheTgtID = cacheKey
if extraData == cacheFitID:
plotKeysToClear.add(cacheKey)
elif extraData == cacheTgtID:
plotKeysToClear.add(cacheKey)
for cacheKey in plotKeysToClear:
del self._plotCache[cacheKey]
# Wipe out whole plot cache otherwise
else:
self._plotCache.clear()
return
# Clear plot cache
plotKeysToClear = set()
for cacheKey in self._plotCache:
cacheFitID, cacheTgtType, cacheTgtID = cacheKey
if fitID == cacheFitID:
plotKeysToClear.add(cacheKey)
elif fitID == cacheTgtID:
plotKeysToClear.add(cacheKey)
for cacheKey in plotKeysToClear:
del self._plotCache[cacheKey]
self._clearInternalCache(fitID=fitID)
# And process any internal caches graphs might have
self._clearInternalCache(reason, extraData)
def _clearInternalCache(self, fitID):
def _clearInternalCache(self, reason, extraData):
return
# Calculation stuff
@@ -219,12 +223,13 @@ class FitDataCache:
def __init__(self):
self._data = {}
def clear(self, fitID):
if fitID is None:
self._data.clear()
elif fitID in self._data:
def clearForFit(self, fitID):
if fitID in self._data:
del self._data[fitID]
def clearAll(self):
self._data.clear()
# noinspection PyUnresolvedReferences
from gui.builtinGraphs import *

View File

@@ -23,6 +23,7 @@ from eos.const import FittingHardpoint
from eos.utils.spoolSupport import SpoolType, SpoolOptions
from eos.utils.stats import DmgTypes
from gui.builtinGraphs.base import FitGraph, XDef, YDef, Input, VectorDef
from service.const import GraphCacheCleanupReason
from .calc import getTurretMult, getLauncherMult, getDroneMult, getFighterAbilityMult, getSmartbombMult, getBombMult, getGuidedBombMult
from .timeCache import TimeCache
@@ -33,8 +34,16 @@ class FitDamageStatsGraph(FitGraph):
super().__init__()
self._timeCache = TimeCache()
def _clearInternalCache(self, fitID):
self._timeCache.clear(fitID)
def _clearInternalCache(self, reason, extraData):
# Here, we care only about fit changes and graph changes.
# - Input changes are irrelevant as time cache cares only about
# time input, and it regenerates once time goes beyond cached value
# - Option changes are irrelevant as cache contains "raw" damage
# values which do not rely on any graph options
if reason == GraphCacheCleanupReason.fitChanged:
self._timeCache.clearForFit(extraData)
elif reason == GraphCacheCleanupReason.graphSwitched:
self._timeCache.clearAll()
# UI stuff
internalName = 'dmgStatsGraph'
@@ -283,8 +292,10 @@ class FitDamageStatsGraph(FitGraph):
# Damage data per key getters
def _getDpsPerKey(self, fit, time):
# Use data from time cache if time was not specified
if time is not None:
return self._timeCache.getDpsDataPoint(fit, time)
# Compose map ourselves using current fit settings if time is not specified
dpsMap = {}
defaultSpoolValue = eos.config.settings['globalDefaultSpoolupPercentage']
for mod in fit.modules:
@@ -303,8 +314,10 @@ class FitDamageStatsGraph(FitGraph):
return dpsMap
def _getVolleyPerKey(self, fit, time):
# Use data from time cache if time was not specified
if time is not None:
return self._timeCache.getVolleyDataPoint(fit, time)
# Compose map ourselves using current fit settings if time is not specified
volleyMap = {}
defaultSpoolValue = eos.config.settings['globalDefaultSpoolupPercentage']
for mod in fit.modules:

View File

@@ -21,6 +21,7 @@
import math
from eos.const import FittingModuleState
from service.const import GraphCacheCleanupReason
from .base import FitGraph, XDef, YDef, Input, FitDataCache
@@ -33,8 +34,11 @@ class FitWarpTimeGraph(FitGraph):
super().__init__()
self._subspeedCache = SubwarpSpeedCache()
def _clearInternalCache(self, fitID):
self._subspeedCache.clear(fitID)
def _clearInternalCache(self, reason, extraData):
if reason == GraphCacheCleanupReason.fitChanged:
self._subspeedCache.clearForFit(extraData)
elif reason == GraphCacheCleanupReason.graphSwitched:
self._subspeedCache.clearAll()
# UI stuff
internalName = 'warpTimeGraph'

View File

@@ -31,6 +31,7 @@ import gui.globalEvents as GE
import gui.mainFrame
from gui.bitmap_loader import BitmapLoader
from gui.builtinGraphs.base import FitGraph
from service.const import GraphCacheCleanupReason
from service.settings import GraphSettings
from .panel import GraphControlPanel
@@ -152,18 +153,18 @@ class GraphFrame(wx.Frame):
def OnFitChanged(self, event):
event.Skip()
self.getView().clearCache(fitID=event.fitID)
self.clearCache(reason=GraphCacheCleanupReason.fitChanged, extraData=event.fitID)
self.draw()
def OnGraphOptionChanged(self, event):
event.Skip()
self.getView().clearCache()
self.clearCache(reason=GraphCacheCleanupReason.optionChanged)
self.draw()
def OnGraphSwitched(self, event):
view = self.getView()
GraphSettings.getInstance().set('selectedGraph', view.internalName)
self.clearCache()
self.clearCache(reason=GraphCacheCleanupReason.graphSwitched)
self.ctrlPanel.updateControls()
self.draw()
event.Skip()
@@ -177,8 +178,8 @@ class GraphFrame(wx.Frame):
def getView(self):
return self.graphSelection.GetClientData(self.graphSelection.GetSelection())
def clearCache(self, fitID=None):
self.getView().clearCache(fitID=fitID)
def clearCache(self, reason, extraData=None):
self.getView().clearCache(reason, extraData)
def draw(self):
global mpl_version

View File

@@ -25,6 +25,7 @@ import wx
from gui.bitmap_loader import BitmapLoader
from gui.contextMenu import ContextMenu
from service.const import GraphCacheCleanupReason
from service.fit import Fit
from .input import ConstantBox, RangeBox
from .lists import FitList, TargetList
@@ -118,8 +119,8 @@ class GraphControlPanel(wx.Panel):
self.SetSizer(mainSizer)
self.drawTimer = wx.Timer(self)
self.Bind(wx.EVT_TIMER, self.OnDrawTimer, self.drawTimer)
self.inputTimer = wx.Timer(self)
self.Bind(wx.EVT_TIMER, self.OnInputTimer, self.inputTimer)
self._setVectorDefaults()
def updateControls(self, layout=True):
@@ -258,12 +259,12 @@ class GraphControlPanel(wx.Panel):
def OnFieldChanged(self, event):
event.Skip()
self.drawTimer.Stop()
self.drawTimer.Start(Fit.getInstance().serviceFittingOptions['marketSearchDelay'], True)
self.inputTimer.Stop()
self.inputTimer.Start(Fit.getInstance().serviceFittingOptions['marketSearchDelay'], True)
def OnDrawTimer(self, event):
def OnInputTimer(self, event):
event.Skip()
self.graphFrame.clearCache()
self.graphFrame.clearCache(reason=GraphCacheCleanupReason.inputChanged)
self.graphFrame.draw()
def getValues(self):

View File

@@ -117,3 +117,11 @@ class GraphDpsDroneMode(IntEnum):
auto = 1
followAttacker = 2
followTarget = 3
@unique
class GraphCacheCleanupReason(IntEnum):
fitChanged = auto()
graphSwitched = auto()
inputChanged = auto()
optionChanged = auto()