ECO : OCLPSHandle

So far in my ECO examples, I’ve been ignoring the issue of performance. I’ve been behaving as if my application will perform identically whether I have 10 objects or 1,000,000 objects. Obviously, this is absurd, so I want to start dealing with this issue. There are many things you can do to control the performance of your ECO app, and this first article will look at one of them, specifically the OCLPSHandle.

Look at the following OCL for example

Person.allInstances->select(Age < 18)

Hopefully by now you recognise that this OCL will return a collection of all Person objects that have the value of their Age attribute less than 18. If we use an ExpressionHandle to execute this OCL, as we have been in all our examples so far, a few things could happen. Firstly, let’s assume that our ECOSpace is empty, so any Person object we wish to access will need to be loaded from the database (we’ll deal later with the case where our ECOSpace is not empty).

So, how can we see what happens when we request this OCL to be executed? There are a couple of tools that I find useful in this type of situation. One is some sort of SQL monitor, so that I can view the actual SQL being executed by the ECO Framework. The other is the OptimizeIt Profiler for .NET, a CPU and Memory profiler that ships with the Architect edition of Delphi and C#Builder. The Memory Profiler in OptimizeIt allows me to peer inside my ECOSpace and see exactly what objects are in memory.

Back to our example, however. The ExpressionHandle behavior is that the select filter above will be executed by the ECOSpace. If we look at the contents of our ECOSpace before executing this OCL in an ExpressionHandle we can see that there are no Person objects instantiated (note the filter I have placed in OptimizeIt, allowing me to only view my domain objects).

When I execute this OCL using an ExpressionHandle, a number of SQL statements are executed. My example is using SQL Server, and in this case, firstly ECO executes this:

SELECT BOLD_ID, BOLD_TYPE FROM Person

Then the BOLD_ID’s returned from this statement are used in the following SQL, to actually return the complete objects:

SELECT BOLD_ID, BOLD_TYPE, Firstname, Lastname, Age FROM Person WHERE BOLD_ID IN (…)

where the list of BOLD_ID’s are inserted between the braces after the IN statement.

Think about this for a moment. This means that all my Person objects will be loaded from my database into my ECOSpace, then the ECOSpace will filter out the correct Person objects and return my collection. While this might be fine for 9 objects as I have, what if I have 10,000 objects, or 100,000, or 1,000,000? This will rapidly become a problem. Just to be sure, this screenshot from OptimizeIt shows that the ECOSpace after this statement is executed holds 9 Person objects, even though my Grid only displays the 2 that match my select statement.

So, how can we exercise some control over this? Well, this is where you can use a component called OCLPSHandle. The PS in the name stands for Persistent Store, because this component will attempt to convert the OCL into a SQL Statement so that the filtering in this case will be executed by the backend database rather than the ECOSpace. So, the exact same OCL as above, but loaded into an OCLPSHandle rather than an ExpressionHandle, results in the following SQL being executed:

SELECT BOLD_ID FROM Person WHERE (Age < 18)

Note the very important WHERE clause, which means the database will do the heavy lifting for us and only return the records that match the OCL filter. ECO can then request the full data only for the required objects. Again, OptimizeIt shows us that after this OCL is executed, only the 2 matching objects exist in our ECOSpace.

And note the end result in our Grid is the same:

Not only is this much more efficient over the network and more efficient in terms of memory, it also executes a lot faster. There are a couple of downsides (c’mon, nothing comes for free). Whereas an ExpressionHandle will execute its OCL automatically, we need to call the OCLPSHandle.Execute method in order for it to execute the OCL and return the result. Still, a small price to pay for such improved performance.

Secondly, the OCLPSHandle, by its very nature, can only return objects that are stored in the database. If there was a Person object in memory that matched my OCL filter, but that had not yet been persisted to the database, the OCLPSHandle would not by default include that in the resulting collection. This can be worked around of course, and Christophe Floury in his excellent "Unleashing Enterprise Models" (C#Builder version / Delphi version) whitepapers shows example source for this very issue. Basically he uses the OCLPSHandle as above, then interrogates the ECOSpace and adds any Person objects to the resulting collection that have not yet been saved and that match the filter.

So, we can now deal much more effectively with large numbers of objects. There is more we can do to tweak ECO’s performance, but that will have to wait for a future article.

Technorati Tags: ,,

Be the first to leave a comment. Don’t be shy.

Join the Discussion

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>