Re: [Modeling-users] entity import takes a lot of cpu
Status: Abandoned
Brought to you by:
sbigaret
From: Sebastien B. <sbi...@us...> - 2003-02-20 17:36:33
|
Hi, I'm answering very quickly so please excuse if my typos and bad engli= sh. Yannick Gingras <yan...@sa...> writes: > On Wednesday 19 February 2003 01:35 pm, Yannick Gingras wrote: > > This delay is not showed in the python profiler so I assume that th= e time > > is spent in a C module. Is the XML parser that CPU hungry ? >=20 > Oups ! >=20 > The delay clearly shows in the profiler, the import statement was exe= cuted=20 > before I start profiling.=20=20 >=20 > [snip] > It seems clear to me that either we our DOM implementation is really > unefficient or my model is too complex. Having 40 entities in my > model, I think it should be easy to parse. >=20 > Anyone had the same problem ? You're not alone! Loading the xml-model *does* consume a lot of cpu. At the very beginning I had a simple sax parser, but I quickly switched to DOM & XPath because it made the implementation a lot clearer. However, I kind of regret this by now because it takes a lot of time to load an xml model. I plan to release another script for ``compiling'' a model, with the generated __init__.py for that purpose. In the meantime I can give you a sample script you may want to adapt to your model (you'll find it at the end of the message). It does something really simple: it loads a model, pickles it, and drops the result into a dedicated module's string-field (dropping it in a model makes it possible to install it w/ distutils, as usual). This makes the process of loading a model a lot quicker; however pickle is very sensitive wrt to its environment, hence great care must be taken so that the python executable compiling the model is the very same than the one loading it, being executed on the same platform, etc. It also requires a little adaptation of the generated __init__.py, you'll also find sample code for that at the end of the message (don't forget to query/replace all occurences of MODEL_NAME with yours). Sorry, I do not have the time to check that everything will work as expected but it's mostly copy-pasted from a working project, hopefully the changes you may have to make won't be too expensive. You can consider that these two samples of code are in public domain. Please tell me if you have any problem with this. -- S=E9bastien. ------------------------------------------------------------------------ #! /usr/bin/env python """ compile_model.py ``Compile'' an xml_model into two python modules, model_<modelName>.p= y and model_<modelName>_pickled.py: - model_<model_name>.py: contains the whole xml-file in a single mo= dule attribute: model_src =20=20 - model_<modelName>_pickled.py: the second one contains a single at= tribute as well: model_pickle, which is a raw string to be loaded by cPickle.loads() =20=20=20=20=20=20 Written by: Sebastien Bigaret """ import sys, getopt def loadModel(xmlFilePath): """ Creates a python module (file: model_<modelName>.py) and dumps the content of the file 'xmlFilePath' in a string attribute named 'model_= src' """ from Modeling import ModelSet ms=3DModelSet.ModelSet() ms.addModelFromXML({'file': xmlFilePath}) model=3Dms.models()[0] model._modelSet=3DNone return model def write_xml_model_in_python_module(xmlFilePath, modelName): """ Creates a python module (file: model_<modelName>.py) and dumps the content of the file 'xmlFilePath' in a string attribute named 'model_= src' """ xml=3Dopen(xmlFilePath, 'r') file=3Dopen('model_%s.py'%modelName, 'w') file.write('model_src=3D"""') s=3Dxml.readline() while s!=3D'': file.write(s) s=3Dxml.readline() file.write('"""\n') xml.close() file.close() =20=20 def write_pickled_model(model): """ Creates a python module (file: model_<modelName>_pickle.py) and dumps= a pickled version of the supplied model in module's attribute 'model_pi= ckle'. """ import cPickle file=3Dopen('model_%s_pickle.py'%model.name(), 'w') file.write('model_pickle=3Dr"""') pickled=3DcPickle.dump(model, file) file.write('"""\n') file.close() def usage(prgName, exitStatus=3DNone): print """%s <model.xml> ``Compile'' an xml_model into two python modules, model_<modelName>.py = and model_<modelName>_pickled.py. - model_<model_name>.py: contains the whole xml-file in a single modu= le attribute: model_src - model_<modelName>_pickled.py: the second one contains a single attr= ibute as well: model_pickle, which is a raw string to be loaded by cPickle.loads() Options ------- -h Prints this message """ % prgName if exitStatus is not None: sys.exit(exitStatus) def main(argv): me=3Dargv[0] try: options, args =3D getopt.getopt(sys.argv[1:], 'h') except getopt.GetoptError,msg: print me, msg usage(me, 1) =20=20=20=20 verbose=3D0 =20=20 for k, v in options: if k=3D=3D'-h': usage(me, 0) if len(args)!=3D1: usage(me,1) =20=20=20=20 model=3DloadModel(args[0]) write_xml_model_in_python_module(args[0], model.name()) write_pickled_model(model) =20 if __name__ =3D=3D "__main__": main(sys.argv) ------------------------------------------------------------------------ ------------------------------------------------------------------------ # modified __init__.py for your package ## ## !!! REPLACE ALL OCCURRENCES OF MODEL_NAME WITH _YOUR_ modelName !!! ## from Modeling import ModelSet import os, warnings, cStringIO, traceback def loadModel(): """ Loads the model. It searches for: 1. a pickled raw string stored in attribute 'model_pickle' in module 'model_<modelName>_pickle', if it exists 2. then, a xml-string stored in attribute 'model_str' in module 'model_<modelName>', if it exists 3. last, a xml file 'model_<model_Name>.xml' cf. script compile_model.py and its usage """ try: from model_MODEL_NAME_pickle import model_pickle import cPickle m=3DcPickle.loads(model_pickle) ModelSet.defaultModelSet().addModel(m) model=3DModelSet.defaultModelSet().modelNamed('MODEL_NAME') except: exc=3DcStringIO.StringIO() traceback.print_exc(file=3Dexc) warnings.warn("Couldn't load model from pickle'\n"\ "Reason:\n%s"%exc.getvalue()) del exc else: return =20=20 try: from model_MODEL_NAME import model_src ModelSet.defaultModelSet().addModelFromXML({'string': model_src}) model=3DModelSet.defaultModelSet().modelNamed('MODEL_NAME') except: exc=3DcStringIO.StringIO() traceback.print_exc(file=3Dexc) warnings.warn("Couldn't load model from 'model_MODEL_NAME.py'\nReas= on:\n%s"%exc.getvalue()) del exc else: return # Or, alternatively: use the xml file (ok for dev. mode, not for inst= all w/ # distutils) # from os import getcwd, path mydir =3D os.path.abspath(os.path.dirname(__file__)) xmlmodelPath=3Dpath.join(mydir,'model_MODEL_NAME.xml') ModelSet.defaultModelSet().addModelFromXML({'file': xmlmodelPath}) model=3DModelSet.defaultModelSet().modelNamed('MODEL_NAME') if ModelSet.defaultModelSet().modelNamed('MODEL_NAME') is None: loadModel() ------------------------------------------------------------------------ |