epsilonlabs/emc-metaedit

Cache property values

Opened this issue · 1 comments

To improve performance, it'd be nice if we could retrieve all properties of a model element in one go instead of going back to the SOAP API for every property call.

Below are Steve Kelly's suggestions on this:

You could look at the existing allPropertiesValues, which does exactly that:
https://www.metacase.com/support/51/manuals/mwb/Mw-9_4_2.html
MEAnyArray allPropertiesValues (MEOop receiver). Returns an MEAnyArray of the values of the properties of the receiver argument, a NonProperty MEOop.

The bigger problem though is that you need the property names: either type names, as you currently use, or local names - the name of the slot in the object type. The latter is better, as that is what the use sees, and also allows to distinguish between the same property type used more than once in the same object type (e.g. a String property "First name" used in a Person object as "First Name", "Mother's First Name" and "Father's First Name"). However, with 5.1 you'll have to stick with property type names, as there's no API command to retrieve local names (there wasn't much need for it with non-meta-use of the API: there you know the properties you want, so you simply ask for them by index rather than name.)

For each object type, you can get the properties of an instance with allProperties(), and then the type of each property with type(). After the first instance, you don't need to ask again: just cache the property type names (or their mapping to indexes). That way, your example script will need to call:

for each type from which we look up a property value:
1 * allProperties(firstClassWeFind)
+numberOfPropertiesInType * (type() + typeName())

For each time we look up a property of an instance:
1 * valueAt()

You can cut it even more if you often want more than one property value from the same instance object: instead of calling valueAt, call allPropertiesValues and cache them. That should keep the number of API calls to a minimum: I'd hope at least 2-3 times faster than your current approach. You can also save a small amount extra at the start if you only call type()+typeName() lazily, and only until you find the desired property type name.

Basically you'd be using lazy loading and caching to build up what you want: having all the information locally, so you don't need to make lots of API calls. Compared to a naive "downloadWholeModel()" this saves at least on memory, and also on time if the script only accesses a small part of the model (as your example script does).