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:
@@ -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 *
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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'
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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):
|
||||
|
||||
@@ -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()
|
||||
|
||||
Reference in New Issue
Block a user