Author Topic: Speed Improvement  (Read 13766 times)

0 Members and 1 Guest are viewing this topic.

DBARANAS

  • Guest
Re: Speed Improvement
« Reply #15 on: August 07, 2007, 12:08:39 AM »
Dave,

DO NOT mix transactions and the open/close paradigm - you will get unpredictable results. Use one or the other, but not both.


Thanks Glenn

I was trying to just use ONLY open/close before and now I can this part working without any use of transactions

Code: [Select]
       
Dim bt As BlockTable = DirectCast(db.BlockTableId.Open(OpenMode.ForRead, False), BlockTable)
        Dim id As ObjectId = bt(BlockTableRecord.ModelSpace)
        Dim br As BlockTableRecord = DirectCast(id.Open(OpenMode.ForWrite, False), BlockTableRecord)

'Then make stuff
'then

bt.close


I get 3 warnings....2 saying use "GetObject" instead and the last one on bt.close "Use Transaction Instead"

"AddNewlyCreatedDBObject" is now a transaction method "tr.AddNewly...........

I am wondering with those obsolete warnings ..... they did not break this open/close way to force you to use transactions

So it works except that without having AddNewlyCreatedDBObject nothing shows up in modelspace

This is using 2007
« Last Edit: August 07, 2007, 06:18:55 AM by Dave Baranas »

DBARANAS

  • Guest
Re: Speed Improvement
« Reply #16 on: August 07, 2007, 01:40:41 AM »
Dave;

Most of my functions now are in C++ and with ARX, never had done any salad mixing of managed-unmanaged code... but going to that place just to improve a 7-10 secs? do not know...  :roll:

Here is attached a function in C++ that does a summation of list of lists and a sample list, maybe will provide an idea of the average timing that takes to process a long list inside of a C++ function and in AutoCAD... (the source code of summation() is in the ARX forum)

Load the list from the VLIDE and then in the command line:

Command: (summation lst)

HTH

Thanks Luis, I tried it and it takes less than 2 seconds. I am trying to understand your algorithm to get an idea of how much work is being done.


Glenn R

  • Guest
Re: Speed Improvement
« Reply #17 on: August 07, 2007, 05:30:50 AM »
Like I said, I was doing this off the top of my head. You're right, AddNewlyCreatedDBObject is a transaction method. What you do is add your entities to the appropriate block table record (Model for example), which you would do normally when using a transaction and that's it.

You may have to do a regenall at the end to see things, but I don't think so.

So, something like this:

BlockTableRecord btr = ......
btr.AddEntity(pSomeEntity);  // or whatever the method is called...

Look up the method in the blocktablerecord class.

LE

  • Guest
Re: Speed Improvement
« Reply #18 on: August 07, 2007, 12:03:56 PM »
Thanks Luis, I tried it and it takes less than 2 seconds. I am trying to understand your algorithm to get an idea of how much work is being done.

Dave;

I being asked to port some routines, that were written in Auto/Visual Lisp and some in VB/A to C++/ARX/MFC, many I have to rethink and redo from scratch, but so far the speed for the new routines or commands exceeds all the expectations....

I'm also, doing some of the same functions in C# just for testing - but they do not want their source in this language, (good for me).

Do not know if you might want to rewrite your (whole) application in C++/ARX/MFC - but it will depend on the time you have for that, might be a lot of fun!.... :)

DBARANAS

  • Guest
Re: Speed Improvement
« Reply #19 on: August 08, 2007, 07:30:50 AM »
Do not know if you might want to rewrite your (whole) application in C++/ARX/MFC - but it will depend on the time you have for that, might be a lot of fun!.... :)

If fun is seeing multiple coronary attacks happen simultaneously when I pitch that one :lmao:

I expanded your summation list x10 and it still comes in under ~10 seconds. Super fast but I wonder how lightweight those objects are compared to Solids.
I am going to modify that simple myline Arx Daniel posted in the ARX group so that it loops making solids and compare those results too.   

If that works OK then I will try go mixed/managed so I can keep the UI in .Net and do the AcDb stuff in ARX where I need the speed gain.

Code: [Select]
static void CRPArxProject1_MyLine(void)
{
AcGePoint3d startPt(1.0, 1.0, 0.0);
AcGePoint3d endPt(10.0, 10.0, 0.0);
AcDbLine *pLine = new AcDbLine(startPt, endPt);

        AcDbBlockTable *pBlockTable = NULL;
AcDbDatabase* pDB = acdbHostApplicationServices()->workingDatabase();
pDB->getSymbolTable(pBlockTable, AcDb::kForRead);
AcDbBlockTableRecord* pBlockTableRecord = NULL;
pBlockTable->getAt(ACDB_MODEL_SPACE, pBlockTableRecord, AcDb::kForWrite);
pBlockTable->close();

        AcDbObjectId lineId = AcDbObjectId::kNull;
pBlockTableRecord->appendAcDbEntity(lineId, pLine);
pBlockTableRecord->close();
pLine->close();
}


« Last Edit: August 08, 2007, 08:15:01 AM by Dave Baranas »

LE

  • Guest
Re: Speed Improvement
« Reply #20 on: August 08, 2007, 10:22:36 AM »
I expanded your summation list x10 and it still comes in under ~10 seconds. Super fast but I wonder how lightweight those objects are compared to Solids.
I am going to modify that simple myline Arx Daniel posted in the ARX group so that it loops making solids and compare those results too.   

If that works OK then I will try go mixed/managed so I can keep the UI in .Net and do the AcDb stuff in ARX where I need the speed gain.

I wrote a very simple function to draw three different types of solids, included is the arx with the command: SOLIDS

It will draw 3000 items, see if helps, to me they are drawn fast enough (and they are a very basic solids) :)

Code: [Select]
bool postToDatabase (AcDbObjectId blockId, AcDbEntity *pEntity)
{
assert( pEntity != NULL );
Acad::ErrorStatus es;
AcDbBlockTableRecordPointer pBlk (blockId, AcDb::kForWrite);
if ( (es = pBlk.openStatus ()) != Acad::eOk )
{
acutPrintf(_T("\nError= %s"), acadErrorStatusText(es));
return (false);
}
es = pBlk->appendAcDbEntity (pEntity);
if (es != Acad::eOk)
{
acutPrintf(_T("\nError= %s"), acadErrorStatusText(es));
}
return (es == Acad::eOk);
}

Code: [Select]
static void makeSomeSolids(void)
{
AcDb3dSolid *pBox = new AcDb3dSolid;
if ( pBox->createBox(10, 10, 10) == Acad::eOk )
{
postToDatabase( acdbCurDwg()->currentSpaceId(), pBox );
pBox->close();
}
AcDb3dSolid *pSphere = new AcDb3dSolid;
if ( pSphere->createSphere(20) == Acad::eOk )
{
postToDatabase( acdbCurDwg()->currentSpaceId(), pSphere );
pSphere->close();
}
AcDb3dSolid *pPyramid = new AcDb3dSolid;
if ( pPyramid->createPyramid(10, 4, 10) == Acad::eOk )
{
postToDatabase( acdbCurDwg()->currentSpaceId(), pPyramid );
pPyramid->close();
}
}

Code: [Select]
static void LESQSummation17_SOLIDS(void)
{
int num = 0;
while (num < 1000)
{
makeSomeSolids();
num++;
}
}
« Last Edit: August 08, 2007, 10:24:46 AM by LE »

DBARANAS

  • Guest
Re: Speed Improvement
« Reply #21 on: August 08, 2007, 06:27:30 PM »
Thanks Luis! for that source, and Daniel, Glenn, and Mick too.

I added an xform and stripped out the spheres and Pyramids which greatly sped things up a lot....lucky for me I just use a few of those.

I played with it and now can say for sure that Arx is way[5X] faster. On average it's 15 sec for 5,000 rectangular solids, 45 sec for 10,000 and 150 sec for 20,000. I did 50,000 before I ran out of memory[1G]. I am starting to see the possibilities hardware coming into the model at the 5,000 level for extra detail when needed with this kind of performance

After 25% into them the hourglass pointer starts flickering until finished which I think is the cheap video card choking to keep up.

Being very green at this I am wondering about if you can get an entry point to an Arx file like lot's of the way's it's done with Dll's and Exe's. Maybe it's as easy as doing a DllImport and passing lists back and forth.

Anyway another Pandora's box to open on the way to the end. Thanks again everyone.




MickD

  • King Gator
  • Posts: 3619
  • (x-in)->[process]->(y-out) ... simples!
Re: Speed Improvement
« Reply #22 on: August 08, 2007, 07:19:05 PM »
PInvoke my be a way, just write your arx functions as C style functions(ie. not part of a class) and you can PInvoke them easily enough. It's actually not that hard to write a managed wrapper either, though passing your entity data back and forth will take a bit of work (type marshaling).

I think the quickest way to do it though would be to pass your list of data to ARX and let it create all the entities without crossing from .net to native with every entity creation, that's the bottle neck. You may want a list of entity ID's that are created, in that case a wrapper would be the way to go I think.
"Short cuts make long delays,' argued Pippin.”
J.R.R. Tolkien

It's Alive!

  • Retired
  • Needs a day job
  • Posts: 8661
  • AKA Daniel
Re: Speed Improvement
« Reply #23 on: August 08, 2007, 11:50:22 PM »
IMO, you need to make a managed wrapper. Once you have done this you can either reference your new .NET assembly as you would any other, or start adding your UI code using C++/CLI. Either way you would need to wrap your code. I am not sure the format of your list, but there already may be methods you can use from the built-in managed wrappers. For example if you can make your native code except a resbuf as an argument, you may be able to use that as your communication link. It’s already wrapped.

PS. If your going to be doing a lot of this type of work in the future, you might want to take the time to learn C++/CLI and making managed wrappers

LE

  • Guest
Re: Speed Improvement
« Reply #24 on: August 09, 2007, 09:59:56 AM »
the two previous comments by the masters, make it sound, that it is very easy.... :)

I started reading this document - among some others - might help you:

http://www.gotw.ca/publications/C++CLIRationale.pdf

MickD

  • King Gator
  • Posts: 3619
  • (x-in)->[process]->(y-out) ... simples!
Re: Speed Improvement
« Reply #25 on: August 09, 2007, 06:03:09 PM »
the two previous comments by the masters, make it sound, that it is very easy.... :)
...

It's not that easy at first, you still need to learn how it works but once you've worked that out away you go..
The best approach would be to use the arx app wizard to create a basic managed dll for you, to handle marshaling the different acad types there are some functions in the 'mgdinterop.h' that comes with the sdk, this is the key!

It's been a while since I have used a wrapper but the sdk will have some samples by now I'd imagine, if you need a hand working it out just holler.
"Short cuts make long delays,' argued Pippin.”
J.R.R. Tolkien

Glenn R

  • Guest
Re: Speed Improvement
« Reply #26 on: August 13, 2007, 09:08:39 PM »
2.8 GHz P4
1.0 Gb ram

To create 10000 3dsolid boxes takes 3 seconds using the open/close paradigm as demonstrated below:

Code: [Select]
[CommandMethod("MakeSolids")]
static public void tcgsMakeSolidsCommand( )
{
// We're simply going to add solids to modelspace

Document doc = acadApp.DocumentManager.MdiActiveDocument;
Database db = doc.Database;
Editor ed = doc.Editor;

BlockTable bt = db.BlockTableId.Open(OpenMode.ForRead, false) as BlockTable;
if(bt == null)
return;

// Get modelspace btr
BlockTableRecord modelspace = bt[BlockTableRecord.ModelSpace].Open(OpenMode.ForWrite, false) as BlockTableRecord;
if(modelspace == null)
return;

// Close blocktable as we don't need it anymore
bt.Close();

DateTime start = DateTime.Now;

for(int i = 0; i < 10000; i++)
{
using(Solid3d sol = new Solid3d())
{
sol.CreateBox(100.0, 50.0, 10.0);
modelspace.AppendEntity(sol);
}
}

// Close modelspace
modelspace.Close();

DateTime finish = DateTime.Now;

TimeSpan elapsed = finish - start;

ed.WriteMessage("\nElapsed time: {0} hours, {1} minutes, {2} seconds.", elapsed.Hours, elapsed.Minutes, elapsed.Seconds);

}

Glenn R

  • Guest
Re: Speed Improvement
« Reply #27 on: August 14, 2007, 12:26:48 AM »
...and the equivalent transactional code (below) to the above, takes 6.4 seconds...double the time.

Code: [Select]
Document doc = acadApp.DocumentManager.MdiActiveDocument;
Database db = doc.Database;
Editor ed = doc.Editor;

DateTime start = DateTime.Now;

Transaction tr = db.TransactionManager.StartTransaction();

using(tr)
{
BlockTable bt = tr.GetObject(db.BlockTableId, OpenMode.ForRead, false) as BlockTable;
if(bt == null)
return;

BlockTableRecord modelspace = tr.GetObject(bt[BlockTableRecord.ModelSpace], OpenMode.ForWrite, false) as BlockTableRecord;
if(modelspace == null)
return;

for(int i = 0; i < 10000; i++)
{
using(Solid3d sol = new Solid3d())
{
sol.CreateBox(100.0, 50.0, 10.0);
modelspace.AppendEntity(sol);
tr.AddNewlyCreatedDBObject(sol, true);
}
}

tr.Commit();
}

DateTime finish = DateTime.Now;

TimeSpan elapsed = finish - start;

ed.WriteMessage("\nElapsed time: {0} hours, {1} minutes, {2}.{3} seconds.", elapsed.Hours, elapsed.Minutes, elapsed.Seconds, elapsed.Milliseconds);

Glenn R

  • Guest
Re: Speed Improvement
« Reply #28 on: August 14, 2007, 12:39:07 AM »
Just for kicks, I added 2 more solids; a wedge and a sphere, into the 10000 iteration loop, thereby effectively creating 30000 3d solids.

Using a transaction, the elapsed time was 36.702 seconds.
Using open/close, the elapsed time was 23.843 seconds.

MickD

  • King Gator
  • Posts: 3619
  • (x-in)->[process]->(y-out) ... simples!
Re: Speed Improvement
« Reply #29 on: August 14, 2007, 12:57:24 AM »
~30% saving, not bad!

I think his biggest hurdle though could be all the transformations, maybe these take even longer than a simple solid creation perhaps??
"Short cuts make long delays,' argued Pippin.”
J.R.R. Tolkien