Book a Demo

Author Topic: Unit testing & java API performance  (Read 7137 times)

tanja

  • EA User
  • **
  • Posts: 71
  • Karma: +0/-0
    • View Profile
Unit testing & java API performance
« on: September 09, 2010, 12:29:18 am »
I'm getting desperate with the time it takes to open my small test model with Java API -  3MB .eap file with ~20 packages and ~100 classes:

14 sec for eaRep.OpenFile(absFilePath)!

The file is excluded from the scan-on-access of the anti-virus software.

To build in-memory representation of the model, by visiting recursively packages with their content (classes, associations, operations, attributes, class diagrams, dependencies, realizations), it takes some 1min 20sec; java processing is of the order of <1sec, everything else is access to EA model through its API.

Any idea on how to write unit tests for the code using such a slow API - I'm getting tired of waiting and then reading logs?

EA 7.5, build 850, Java 6;
WinXP SP3
ThinkPad T60p, Core Duo, [email protected] GHz, 3GB RAM

Geert Bellekens

  • EA Guru
  • *****
  • Posts: 13523
  • Karma: +574/-33
  • Make EA work for YOU!
    • View Profile
    • Enterprise Architect Consultant and Value Added Reseller
Re: Unit testing & java API performance
« Reply #1 on: September 09, 2010, 04:24:49 pm »
Tanja,

The speed of EA is what it is.
How do those 14 seconds compare to opening the model using the EA client?
Building a full cached representation trough recursion is a BAD idea.
That will take ages.
What I do to cache my elements is use the Repository.GetElementSet.
If I need attributes, operations, or connectors then I first get a list of id's using Repository.SQLQuery and then get the item using the Repository.getXXXbyID operations.

Here's an example of my caching operation for elements for our SQL server repository. The same can be done with a local eap file, but then you'll have to rewrite the query to match to Access "SQL" syntax.
Code: [Select]
/// <summary>
        /// adds all elements in the model to the cache
        /// </summary>
        public void addAllElementsToCache(string startingPackageID)
        {
            //first check if we are dealing with a local eap file in MS Access format.
            //in that case we cannot perform the query with the unions
            bool localEAPFile = true;
            string connection = this.wrappedModel.ConnectionString;
            if (connection.ToLower().EndsWith( ".eap"))
            {
                //could be an eap file, or could be a shortcut file.
                //figure it out based on the size of the file
                try
                {
                FileInfo connectionInfo = new FileInfo(connection);
                if (connectionInfo.Length > 1000)
                {
                    localEAPFile = true;
                }
                else
                {
                    localEAPFile = false;
                }

                }catch (Exception)
                {
                    localEAPFile = false;
                }
            }
            Logger.log("start caching elements");
            //build the sql string to get all the object fromthe starting package and 9 levels of packages underneath.
            //there is a better way using a recursive query, but these are not supported in sql 2000 yet (only from sql 2005)
            string sqlGetElements = @" SELECT o.Object_ID FROM t_object as o
                                    left join t_package p on o.Package_ID = p.Package_ID
                                    left join t_package p2 on p.Parent_ID = p2.Package_ID
                                    left join t_package p3 on p2.Parent_ID = p3.Package_ID
                                    left join t_package p4 on p3.Parent_ID = p4.Package_ID
                                    left join t_package p5 on p4.Parent_ID = p5.Package_ID
                                    left join t_package p6 on p5.Parent_ID = p6.Package_ID
                                    left join t_package p7 on p6.Parent_ID = p7.Package_ID
                                    left join t_package p8 on p7.Parent_ID = p8.Package_ID
                                    left join t_package p9 on p8.Parent_ID = p9.Package_ID

                                    where
                                    p.package_ID = " + startingPackageID + @"
                                        or p2.package_ID = " + startingPackageID + @"
                                        or p3.package_ID = " + startingPackageID + @"
                                        or p4.package_ID = " + startingPackageID + @"
                                        or p5.package_ID = " + startingPackageID + @"
                                        or p6.package_ID = " + startingPackageID + @"
                                        or p7.package_ID = " + startingPackageID + @"
                                        or p8.package_ID = " + startingPackageID + @"
                                        or p9.package_ID = " + startingPackageID;
            try
            {
                if (!localEAPFile)
                {
                    //we only do caching when working on an remote database
                    EAWrapperFactory.createEAWrappers(this, this.wrappedModel.GetElementSet(sqlGetElements, 2));
                }
                Logger.log("end caching elements");
            }
            catch (Exception)
            {
                // oh well, caching failed, no biggy, we can work without caching, its just a bit slower
                Logger.logError("Caching failed");
            }
        }

tanja

  • EA User
  • **
  • Posts: 71
  • Karma: +0/-0
    • View Profile
Re: Unit testing & java API performance
« Reply #2 on: September 09, 2010, 04:44:29 pm »
Thanks Geert.

Opening file from the file system takes 7 sec (vs. 14 sec from the API call). I have noticed that EA7.5 significantly increased that start-up time as compared to EA7.1, but had never measured how long it was with EA7.1 (because you never notice when something is fast enough).

I'm using the java API precisely not to dig into underlying DB implementation and SQL...

Geert Bellekens

  • EA Guru
  • *****
  • Posts: 13523
  • Karma: +574/-33
  • Make EA work for YOU!
    • View Profile
    • Enterprise Architect Consultant and Value Added Reseller
Re: Unit testing & java API performance
« Reply #3 on: September 09, 2010, 06:14:17 pm »
Tanja,

The biggest bottleneck in EA performance (and the tools you write agains its API) are the enormous amounts of database calls.
For some EA collection, merely iterating the collection results in two database calls for each iteration.
So the only way I see to avoid the database calls is to group the database calls into one SQL statement, retrieving all I need to know.
Remember, creating the Objects, and iterating the collections is what takes most time, so avoid this if possible.
Only instantiate an EA object if you really need it, and only iterate a specific collection once.

Geert

tanja

  • EA User
  • **
  • Posts: 71
  • Karma: +0/-0
    • View Profile
Re: Unit testing & java API performance
« Reply #4 on: September 09, 2010, 06:49:55 pm »
Thanx again, Geert.

Currently, I do iterate on collections once and only once, and I definitely am inspecting the EA objects returned for their properties, which are again sometimes collections - i.e., in your terms, I instantiate every single object returned by API - in order to create my own in-memory model and then do "thousand things" with these in-memory objects - within a couple of seconds.

I would have to drastically redesign my application, for it to work with IDs and SQL. Furthermore, certain EA objects don't even have their own ID, just the ParentID - for a Java developer, it's the world up-side-down...

Geert Bellekens

  • EA Guru
  • *****
  • Posts: 13523
  • Karma: +574/-33
  • Make EA work for YOU!
    • View Profile
    • Enterprise Architect Consultant and Value Added Reseller
Re: Unit testing & java API performance
« Reply #5 on: September 09, 2010, 07:04:31 pm »
Tanja,

Do you create a complete in-memory model, or do you use a lazy loading principle for creating the in-memory model.
Depending on the type of application you are writing that could make a big difference.
If you only need a part of the objects then you don't need to build the whole model in memory, just instantiate what you need.

Geert


tanja

  • EA User
  • **
  • Posts: 71
  • Karma: +0/-0
    • View Profile
Re: Unit testing & java API performance
« Reply #6 on: September 09, 2010, 07:24:34 pm »
I create the in-memory model on the fly, by "visiting" the first root package, then its contents, then the contents of its contents, and so on. For each EA object returned, I deal with it once (to create my in-memory representation), and never touch that EA object again. Think of it as a SAX parser which in the end allows to produce a DOM tree :-)

I do need the whole content of the EA model, because my application is a validation engine with many rules to check the UML model content against.

Geert Bellekens

  • EA Guru
  • *****
  • Posts: 13523
  • Karma: +574/-33
  • Make EA work for YOU!
    • View Profile
    • Enterprise Architect Consultant and Value Added Reseller
Re: Unit testing & java API performance
« Reply #7 on: September 09, 2010, 09:12:17 pm »
Quote
I do need the whole content of the EA model, because my application is a validation engine with many rules to check the UML model content against.

Ha, same here ;D
The performance issues were exactly the reason why I used the operation I posted above.
I think you'll find that is it faster then recursing the whole model.
Filling the element cache takes about three minutes for about 5.000 elements.

Geert

Daniel Siegl

  • EA User
  • **
  • Posts: 42
  • Karma: +0/-0
    • View Profile
Re: Unit testing & java API performance
« Reply #8 on: September 10, 2010, 01:40:02 am »
If you want to run your tests on a build server you might find this interesting:
http://blog.lieberlieber.com/2009/09/16/running-enterprise-architect-on-a-server/

tanja

  • EA User
  • **
  • Posts: 71
  • Karma: +0/-0
    • View Profile
Re: Unit testing & java API performance
« Reply #9 on: September 10, 2010, 01:44:31 am »
Thanks for your reaction Daniel, but I just have corporate edition installed on my machine and I always run EA locally.

tanja

  • EA User
  • **
  • Posts: 71
  • Karma: +0/-0
    • View Profile
Re: Unit testing & java API performance
« Reply #10 on: September 10, 2010, 04:15:32 am »
I've just tried the GetElementSet("",2) and I get all the classes, packages and notes. If playing then with ParentID, I guess I can deduce relationships I need.

However, for everything else (methods, attributes, connectors, constraints, diagrams, name it!) there is no such a method to fetch them all. Then I have to go again with collections on elements (like GetDiagrams(), GetAttributes() etc.).

Any idea on how to get to all the IDs of everything in the .eap and then work with it? I'm really getting tired of this exercise and may just consider searching for another tool altogether.

Geert Bellekens

  • EA Guru
  • *****
  • Posts: 13523
  • Karma: +574/-33
  • Make EA work for YOU!
    • View Profile
    • Enterprise Architect Consultant and Value Added Reseller
Re: Unit testing & java API performance
« Reply #11 on: September 10, 2010, 02:50:04 pm »
Tanja,

What you could do for attributes, connector, ... is to get the id's from the database using either Repository.SQLQuery, or use one of the enumerate operations on the Project Interface.
And then use the Repository.GetXXXByID operations to get the actual objects.
But i'm not sure that will make a big difference in the performance.

For reference, my modelvalidator runs about 15 minutes on a package (and subpackages) with about 5000 elements.
It returns about 20.000 errors in an excel file.
The whole model contains about 50.000 elements and is stored on a remote SQL Server database.

Geert