08/10/2012

The Right Tools for the Job – AutoCAD Part 5

Leading on from Part 4, and staying with ‘Performance’ I wanted to take a look at some .NET code and show you how to access the DWG database in the fastest way.

Over the years, I’m sure some of you have noticed how I like to write my DWG Database .NET in a very similar way to any code I write in ObjectARX, I try to only use Open/Close() unless I absolutely need to use Transactions.

The reason for this comes from my own personal experience and preferences:

Open/Close is faster than Transaction/StartTransaction

Open/Close can be more easily used in Event/Reactor callbacks, Transaction/StartTransaction can, but you need to really think about what you are doing

Open/Close is neater to write, in my opinion

That said, other members in my team, including the original author of our AutoCAD .NET API, prefer to use the Transaction model because it’s more Object Oriented.

Here’s some code which shows the differences between using Transaction/StartTransaction and Open/Close…

First the Transaction version, which I personally don’t normally like writing…

Now I have shown the differences between the two styles, I should explain that there is actually two more additional styles of coding DWG database handling inside of AutoCAD.NET; that is Transaction.StartOpenCloseTransaction() and ObjectId.GetObject().

The Transaction.StartOpenCloseTransaction() style is exactly the same as the normal Transaction.StartTransaction(), except that it wraps the Open/Close mechanism in a Transaction object. When I show the performance differences further down, you will understand the reasons to use it, but in the meantime, here’s a quick look at the code – the only difference between the ‘StartTransaction’ function above and this one is the call to StartOpenCloseTransaction() instead of StartTransaction()…

The ObjectId.GetObject() style utilizes the normal Transaction object mechanism, but this way gives you a slightly difference access point.

Why would you use ObjectId.GetObject() instead of Transaction.GetObject() I hear some of you ask – basically, the ObjectId.GetObject() obtains the top most transaction in the transaction stack, so it can save time when coding (no need to pass the transaction around) – that said it can cost a few extra CPU cycles to use which you can see affecting the results below.

I have to confess that the sample code above was obtained from an original version that “Jeff H” of TheSwamp.org created as part of his own performance testing that he posted. I really liked what he did (and others that read the same post can relate to it also) so I thought I’d use it here for my own benchmarking – Thanks Jeff H!

His original code had some little bugs in it which he actually pointed out himself; his code opened some objects for read and then those same objects, in different test functions, for write which probably made each test function slightly unfair to the other. I corrected those issues, and removed the extra “false, false” parameters from the Open() and GetObject() see the bottom for the code…

I recommend that you only ever open for write when you absolutely need too, otherwise you may be costing yourself valuable CPU cycles.

Now here are the test results – AutoCAD 2013, 55,000 entities in Model Space, each command run 5 times to average out any of my computer’s normal running tasks interference…

So it seems that StartOpenCloseTransaction(), in this test, even beats Open/Close on performance. It also seems that both of the normal ‘Transaction’ models StartTransaction() and ObjectID.GetObject() are significantly slower, but not much real difference between the two (0.3 of a second).

About The Transaction object in AutoCAD... The Transaction model (StartTransaction()) was invented way back when for a specific reason - transacting multiple writes on the same objects(s) and allowing layered rollbacks of these multi-write transactions.

Here’s what I recommend: If you guys are using StartTransaction(), and you don’t need the multiple write feature I just mentioned in the above paragraph, simply change your StartTransaction() to StartOpenCloseTransaction()…

Comments

Leading on from Part 4, and staying with ‘Performance’ I wanted to take a look at some .NET code and show you how to access the DWG database in the fastest way.

Over the years, I’m sure some of you have noticed how I like to write my DWG Database .NET in a very similar way to any code I write in ObjectARX, I try to only use Open/Close() unless I absolutely need to use Transactions.

The reason for this comes from my own personal experience and preferences:

Open/Close is faster than Transaction/StartTransaction

Open/Close can be more easily used in Event/Reactor callbacks, Transaction/StartTransaction can, but you need to really think about what you are doing

Open/Close is neater to write, in my opinion

That said, other members in my team, including the original author of our AutoCAD .NET API, prefer to use the Transaction model because it’s more Object Oriented.

Here’s some code which shows the differences between using Transaction/StartTransaction and Open/Close…

First the Transaction version, which I personally don’t normally like writing…

Now I have shown the differences between the two styles, I should explain that there is actually two more additional styles of coding DWG database handling inside of AutoCAD.NET; that is Transaction.StartOpenCloseTransaction() and ObjectId.GetObject().

The Transaction.StartOpenCloseTransaction() style is exactly the same as the normal Transaction.StartTransaction(), except that it wraps the Open/Close mechanism in a Transaction object. When I show the performance differences further down, you will understand the reasons to use it, but in the meantime, here’s a quick look at the code – the only difference between the ‘StartTransaction’ function above and this one is the call to StartOpenCloseTransaction() instead of StartTransaction()…

The ObjectId.GetObject() style utilizes the normal Transaction object mechanism, but this way gives you a slightly difference access point.

Why would you use ObjectId.GetObject() instead of Transaction.GetObject() I hear some of you ask – basically, the ObjectId.GetObject() obtains the top most transaction in the transaction stack, so it can save time when coding (no need to pass the transaction around) – that said it can cost a few extra CPU cycles to use which you can see affecting the results below.

I have to confess that the sample code above was obtained from an original version that “Jeff H” of TheSwamp.org created as part of his own performance testing that he posted. I really liked what he did (and others that read the same post can relate to it also) so I thought I’d use it here for my own benchmarking – Thanks Jeff H!

His original code had some little bugs in it which he actually pointed out himself; his code opened some objects for read and then those same objects, in different test functions, for write which probably made each test function slightly unfair to the other. I corrected those issues, and removed the extra “false, false” parameters from the Open() and GetObject() see the bottom for the code…

I recommend that you only ever open for write when you absolutely need too, otherwise you may be costing yourself valuable CPU cycles.

Now here are the test results – AutoCAD 2013, 55,000 entities in Model Space, each command run 5 times to average out any of my computer’s normal running tasks interference…

So it seems that StartOpenCloseTransaction(), in this test, even beats Open/Close on performance. It also seems that both of the normal ‘Transaction’ models StartTransaction() and ObjectID.GetObject() are significantly slower, but not much real difference between the two (0.3 of a second).

About The Transaction object in AutoCAD... The Transaction model (StartTransaction()) was invented way back when for a specific reason - transacting multiple writes on the same objects(s) and allowing layered rollbacks of these multi-write transactions.

Here’s what I recommend: If you guys are using StartTransaction(), and you don’t need the multiple write feature I just mentioned in the above paragraph, simply change your StartTransaction() to StartOpenCloseTransaction()…