Tuesday, 15 September 2015

python - Single SQLAlchemy mapped object resulting in many different instances in memory -



python - Single SQLAlchemy mapped object resulting in many different instances in memory -

i know title convoluted, i'll seek give simplified illustration of i'm trying do. please bear me bit.

i'm working on alternative values calculation , portfolio risk analysis server, , i've run problem i'm not quite sure how address when loading persisted object graph , accessing cached properties i've dynamically added database load.

say have next mapped classes:

base = declarative_base() class portfolio(base): __tablename__ = "portfolios" id = column(integer, primary_key=true) asset_classes = relationship("assetclass", backref="portfolios") class assetclass(base): __tablename__ = "asset_classes" id = column(integer, primary_key=true) portolio_id = column(integer, foreignkey("portfolios.id")) assets = relationship("asset", backref="asset_classes") class asset(base): id = column(integer, primary_key=true) asset_class_id = column(integer, foreignkey("asset_classes.id"))

then load portfolio , initialization follows:

session = session() # pretend there's 1 portfolio portfolio = session.query(portfolio).one() init_portfolio(portfolio) while(keep_server_alive): # session stays open server life gevent.sleep(0) session.close() def init_portfolio(p): # note dynamically added property portfolio.values_store = valuesstore() asset_class in p.asset_classes: init_asset_class(asset_class) def init_asset_class(ac): asset in ac.assets: init_asset(asset)

once initialized utilize long running gevent thread process cost updates , calculate derivative values, follows:

def on_underlying_update(asset, underlying_price): # next line non-deterministically fails attributeerror values_store = asset.asset_class.portfolio.values_store values_store.get_asset_price(asset, underlying_price)

these calculations can quite expensive, valuesstore object has caching strategy store results. on random passes through on_underlying_update function, i'll attributeerror saying portfolio object doesn't have values_store property.

at first confused me, debugged issue bit seemed find kid assetclass objects referring same portfolio might referencing different objects in memory. came believe after using python's id() function check portfolio.id's against memory id's during each access. doing so, routinely find while might have ever access 1 portfolio.id, referencing several different memory addresses depending on kid doing accessing.

i know long winded, , appreciate who's stuck me far. question is, there way me load entire object graph in memory 1 time , once? valuesstore object can expensive resources perspective, , i'd prefer instantiate few times possible.

for reference, i"m using python 2.7.3, sqlalchemy 0.8, gevent 1.0rc2, , i'm experiencing same issue on both windows 7 , os x 10.8.

thanks again.

** edit **

i spent lot of time going through code looking statements cause portfolio object detached current session , attached new one. couldn't find of sort. tried hear sorts of instance , session events, , each time, see "new" portfolio beingness loaded beingness loaded original session.

is possible portfolio object beingness garbage collected? tried testing hypothesis spawning new gevent thread hold onto strong reference portfolio follows:

def keep_portfolio_alive(p): portfolio = p while true: gevent.sleep(0)

this seems solve issue. never see session load portfolio sec time.

** edit 2 **

so i'm not sure, believe i've found problem. when defining relationships between mapped classes, used attribute_mapped_collections instead of normal lists. when initializing classes, iterate on kid objects so:

for asset_class in portfolio.asset_classes.itervalues(): #

since of these classes multiply nested, along hierarchy there class had been referenced using copied-iterator, , referenced own kid classes using copied-iterator. best guess portfolio class ended no strong references between either , parent object, or , of kid objects. gc marked collection @ point.

hope helps in future.

python sqlalchemy

No comments:

Post a Comment