-
Notifications
You must be signed in to change notification settings - Fork 35
Description
This is definitely relevant to #48 and is a spinoff of @bmeyers original cache idea in the rejected PR #42 , and a continuation of the accepted PR #43, that closed the relevant issues #34 and #35 about copies, and of course the ability to delay calculation #59.
The idea is simple, every time you make a calculation in __setattr__
or in calcCells()
:
- check the cache for a similar cell, it's hash should be identical
- if the cell doesn't exist yet, then calculate it and store the cell in a cache, like @bmeyers does in Better memory #42 except just store the entire
PVcell
, no need to serialize it (the cell) right now
The cache should be in pvconstants
and should probably have a limit of 100 or 1000 cells. Any strategy can be used to determine which cells to keep in the cache, for example, a count could be kept of how many times each cell was called, and then the least popular cells are culled as needed.
This cache could be repeated for modules and strings as well.
sample code:
from pvmismatch import *
# pvconstants
pvconst = pvconstants.PVconstants()
# monkey patch for example
pvconst.cache = {'pvcells': {}, 'pvmods': {}, 'pvstrs': {}}
pvconst.cache_maxsize = 100
PARAMS = ['Rs', 'Rsh', 'Isat1_T0', 'Isat2_T0', 'Isc0_T0', 'aRBD', 'bRBD', 'VRBD', 'nRBD', 'Eg', 'alpha_Isc', 'Tcell', 'Ee']
def hash_cell(cell, params=PARAMS):
"""cell params is a dictionary with cell params"""
cell_params = vars(cell)
cell_hash = str()
for k in params:
cell_hash += hex(hash(cell_params[k]))[2:] # omit '0x'
return '0x%s' % cell_hash
This works! Generate two different PVcells
that are identical, but have different memory locations, and the calculated hash is the same.
>>> pvc = pvcell.PVcell()
>>> cell_hash = hash_cell(pvc)
'0x22f50b4c78e2706476d29247d00a1c997714032461851a3c0257edda00dc9c779a6b50b10061000d96c02215ef60x10df5081cebee80591bad56da435c033333333333334011802e8b2dc60be864cccccccccc012a1'
>>> pvconst.cache['pvcells'][cell_hash ] = pvc # cache cell for future
>>> id(pvc)
1880798536480 # different
>>> hash(pvc)
117549908530 # different
>>> pvsys = pvsystem.PVsystem()
>>> new_cell_hash = hash_cell(pvsys.pvstrs[0].pvmods[0].pvcells[0])
'0x22f50b4c78e2706476d29247d00a1c997714032461851a3c0257edda00dc9c779a6b50b10061000d96c02215ef60x10df5081cebee80591bad56da435c033333333333334011802e8b2dc60be864cccccccccc012a1'
>>> new_cell_hash in pvconst.cache['pvcells']
True
>>> id(pvsys.pvstrs[0].pvmods[0].pvcells[0])
1880798601344 # different
hash(pvsys.pvstrs[0].pvmods[0].pvcells[0])
117549912584 # different
then in PVmodules
# in #48 update method
def update(self, cell_dicts):
for pvc, params in cell_dicts.item():
cell_params = vars(self.pvcells[pvc])
cell_params.pop('Icell')
cell_params.pop('Vcell')
cell_params.pop('Pcell')
cell_params.pop('pvconst')
cell_params.pop('_calc_now')
cell_params.update(params)
cell_hash = pvconstants.hash_cell(cell_params)
if cell_hash in self.pvconst.cache['pvcells']:
# use cache
self.pvcells[pvc] = self.pvconst.cache['pvcells'][cell_hash]
else:
# make a new cell
self.pvcells[pvc] = pvcell.PVcell(**params, pvconst=self.pvconst)
self.pvconst.cache['pvcells'][cell_hash] = self.pvcells[pvc]