Performance issue

A

Ashok

H

I have got some real tough task to solve. When i place the shapes on the visio activex 2003 in my c# program it works very much fine and it takes around 5 secs to place 30 shapes with 30 connections over it

But when my input is 150 shapes and above with 200 connections i am really finding it difficult to cut short the time to execute. It consumes around 30 secs to fill the drawing or sometimes more. This performance issue is hiting my program

The option i thought was of threading to be implemented so that the simultaneous execution speeds up the work. But i am not aware of implementing that

If any body can suggest or provide solution on my performance improvement it will be a great help

Thanks & Regard
Ashok Kumar
 
D

dani

Hi Ashok

I had (and still have) also problems with performance with my program
when placing many shapes, and it also takes about 30s to place 200
Shapes with connectors.

Here are some performance enhancements I used in my program (you
probably already used some of them):

- try to make your masters as easy as possible (my solution worked about
20% faster with just rectangles and text instead of my previous master
with background color and several shapes.)
- instead of Drop use the DropMany-method
- don't place all your shapes on the same location on the sheet
- layout all the shapes together instead of laying out each one when drop.
- set the ChangesVisible (and maybe ScreenUpdating) property to false
while drawing.

As for using threading this is only useful if you have more than one
processor in your computer, because only one thread can be executed at a
time on one processor. With just one processor the system is switching
between the threads. And besides, I don't know how this could be
realized with visio.

Daniel
 
A

Ashok

Hi Danie

Thanks a lot for your reply. As you said i am trying to follow the steps. I have'nt worked with Drop Many method. If you have a sample of code please help me in doing that. It will be a great help

Thanks & regard
Ashok
 
D

dani

Hi Ashok,

below is a method (written in Delphi) which uses the DropMany method.

The DropMany-method needs 3 SafeArrays as parameters, in the first one
you need to insert the Masters to be used, in the 2nd one you need to
insert the x and y-coordinates (so the 2nd array is twice as long as the
1st one), and in the 3rd array, the method should return the IDs of the
shapes dropped. I say "should" because this actually doesn't work in my
case.

by the way, TBISVisioElement is a custom class of my programm, and the
..Master property is of type IVMaster.


procedure TBISVisioSchemaEvent.DropAllShapes(shapeObjList: TObjectList);
type
IntegerArray = array of integer;
var
i, low, up: integer;
activePage: IVPage;
vMasters, vPositions: Variant;
aMasters, aPositions, aShapeIDs: PSafeArray;
ArrayBounds : TSafeArrayBound;
begin
if shapeObjList.Count > 0 then begin
activePage := FApplication.ActivePage;

ArrayBounds.lLbound := 0;
ArrayBounds.cElements := shapeObjList.Count;
low := 0;
up := shapeObjList.Count - 1;

vMasters := VarArrayCreate([low,up],varVariant);
vPositions := VarArrayCreate([low,2*up+1],varDouble);

aShapeIDs := nil;

//set the masters coordinates for the shapes to drop
//don't place the shapes on top of each other
for i := low to up do begin
//master of shape i
vMasters := (shapeObjList as TBISVisioElement).Master;
//x-coordinate
vPositions[2*i] := (i+1);
//y-coordinate
vPositions[2*i+1] := 1;
end; //for i

aMasters := PSafeArray(TVarData(vMasters).VArray);
aPositions := PSafeArray(TVarData(vPositions).VArray);

//drop all shapes
FInsertedShapeNr := 0;
activePage.DropMany(aMasters,aPositions,aShapeIDs);

SafeArrayUnLock(aMasters);
SafeArrayUnLock(aPositions);
SafeArrayUnLock(aShapeIDs);
end; //if ShapeObjList.Count > 0
end; //TBISVisioSchemaEvent.DropAllShapes
 
M

Markus Breugst

Hi Ashok,

as I remember you're using C#. So here is also an example in this language.
In our case, the ID output array is correctly filled.

Best regards,
Markus

IVDocument _visioDoc = ...;
IVMaster _masterShape;
Array _masterShapes = new object[_count];
Array _xyPositions = new double[_count * 2];
Array _idArray;
double _xPos = ...;
double _yPos = ...;

// Initialize input Array for DropMany
for (int _index = 0; _index < _count; _index++)
{
_masterShape = ...;
_masterShapes.SetValue( _masterShape, _index );
_xyPositions.SetValue( _xPos, _index * 2 );
_xyPositions.SetValue( _yPos, _index * 2 + 1 );
_yPos = _yPos + ...; // optional (just for creating the shapes at
different coordinates)
}

// Create shapes
_visioDoc.Pages[1].DropMany( ref _masterShapes, ref _xyPositions, out
_idArray );

// Now you can access the shapes in the following way:
IVShapes _vShapes = _visioDoc.Pages[1].Shapes;
int _id = System.Convert.ToInt16( _idArray.GetValue( _index ) );
IVShape _vShape = _vShapes.get_ItemFromID( _id );



Ashok said:
Hi Daniel

Thanks a lot for your reply. As you said i am trying to follow the steps.
I have'nt worked with Drop Many method. If you have a sample of code please
help me in doing that. It will be a great help.
 
M

Mark Nelson [MS]

I can elaborate a bit on the suggestion to simplify your masters. The shape
is the fundamental component of a Visio drawing, so good performance means
minimizing the number of shapes used in that drawing. If you have a master
that is composed of many sub-shapes, each of these counts as a regular shape
for performance. So if you can reduce the number of sub-shapes, you will
have a big impact. Perhaps you can add a second or third geometry section
to a shape instead of grouping more primitive geometric shapes together.
Realistically, the only reason to have sub-shapes at all is to vary the
formatting of a portion of the master or to allow multiple text elements.

--
Mark Nelson
Microsoft Corporation

This posting is provided "AS IS" with no warranties, and confers no rights.


dani said:
Hi Ashok

I had (and still have) also problems with performance with my program
when placing many shapes, and it also takes about 30s to place 200
Shapes with connectors.

Here are some performance enhancements I used in my program (you
probably already used some of them):

- try to make your masters as easy as possible (my solution worked about
20% faster with just rectangles and text instead of my previous master
with background color and several shapes.)
- instead of Drop use the DropMany-method
- don't place all your shapes on the same location on the sheet
- layout all the shapes together instead of laying out each one when drop.
- set the ChangesVisible (and maybe ScreenUpdating) property to false
while drawing.

As for using threading this is only useful if you have more than one
processor in your computer, because only one thread can be executed at a
time on one processor. With just one processor the system is switching
between the threads. And besides, I don't know how this could be
realized with visio.

Daniel
visio activex 2003 in my c# program it works very much fine and it takes
around 5 secs to place 30 shapes with 30 connections over it.really finding it difficult to cut short the time to execute. It consumes
around 30 secs to fill the drawing or sometimes more. This performance issue
is hiting my program.simultaneous execution speeds up the work. But i am not aware of
implementing that.
 
A

Ashok

Hi Daniel, Markus and Mar

I have used your code of "DropMany". It was faster than the actual placement. But the best thing i can do was 28 seconds for placing 250 objects and 160 connections. This also contains Locking the text, rotation of each shape

I have removed all type of other collections and implemented only HASH Table collections. This was the result that could be achieved

I think i will try to improve that timming to cut short to 10-12 seconds. Thanks a lot guys for your combined effort

Thanks & regard
Ashok
 
M

Mark Nelson [MS]

How many Cells are you setting after you drop the shape on the page? Use
SetFormulas wherever possible to set cell values in bulk. Also are the
shapes and connectors you are dropping instances of masters? What about
using a master shape that already has text and rotation locked?

--
Mark Nelson
Microsoft Corporation

This posting is provided "AS IS" with no warranties, and confers no rights.


Ashok said:
Hi Daniel, Markus and Mark

I have used your code of "DropMany". It was faster than the actual
placement. But the best thing i can do was 28 seconds for placing 250
objects and 160 connections. This also contains Locking the text, rotation
of each shape.
I have removed all type of other collections and implemented only HASH
Table collections. This was the result that could be achieved.
I think i will try to improve that timming to cut short to 10-12 seconds.
Thanks a lot guys for your combined effort.
 
A

Ashok

Hi Mar

That was really helpfull. I really reduced the time by some large amount. But still i need to improve. I have improved the timming as mentioned earlier from 28 seconds to 17 seconds. That was good thought to be implemented. Thanks a lot. I think i still need to improve the timming

Thanks & Regard
Ashok
 
M

Mark Nelson [MS]

At this point we would probably need to see your code, or perhaps you could
summarize the calls you make to Visio. I would be interested to know your
computer specification to help gauge how fast or slow things are. You could
also try using basic rectangles to determine whether the difference is in
the shape complexity or in the drop and connect code.

For reference, I wrote some VBA to fill a page with shapes and connect them.
I was able to add 200 flowchart shapes plus connectors to the page in 1.5
seconds on a 1GHz PC. Using DropMany instead of Drop reduced the time by
20%. I've pasted the important code below. The master array is filled with
my shape master and the dynamic connector, in an alternating pattern. The
XYArray has coordinates for each shape and each connector between shapes,
again in an alternating pattern. In the For Loop, I get a shape object for
two Shapes and the Connector I want to glue them together with. Then I glue
each end of the Connector to the Shapes.


Page.DropManyU MasterObjects, XYArray, IDArray

Set Shape1 = Page.Shapes.ItemFromID(IDArray(0))
For i = 2 To 2 * NumInstances - 2 Step 2
Set Connector = Page.Shapes.ItemFromID(IDArray(i - 1))
Set Shape2 = Page.Shapes.ItemFromID(IDArray(i))
Connector.CellsU("BeginX").GlueTo Shape1.CellsU("PinX")
Connector.CellsU("EndX").GlueTo Shape2.CellsU("PinX")
Set Shape1 = Shape2
Next

--
Mark Nelson
Microsoft Corporation

This posting is provided "AS IS" with no warranties, and confers no rights.


Ashok said:
Hi Mark

That was really helpfull. I really reduced the time by some large amount.
But still i need to improve. I have improved the timming as mentioned
earlier from 28 seconds to 17 seconds. That was good thought to be
implemented. Thanks a lot. I think i still need to improve the timming.
 
A

Ashok

Hi Mar

I have implemented in the same way. I have used the drop many method to drop all the objects on the screen.

But unfortunately the situation is, After reading each connection from my collection i will have a situation of connection to be made for a different level object in the hierarchy. so looking at the connection i have put 2 conditions to find the object of different level is at the source of the connection or at the end of connection.

So i place a new object and create the connection between same level object and different level object on the same page which is represented as a connector (with a Circle object)

This type of connections are known at runtime while reading each connection from my collection

Then i use GlueToPos for specifying the area from where the connection generates from the object to the object. So when the diagram is generated finally i end up showing a single object with many ports and with their connection as per kind of the port as input/output port

This process of placing the connection on the left or right side of the object and creation of different level object representing as connector is consuming lots of time

I tried implementing threading concept for connections but ended up seeing the performance become worse. The reason i found behind this is, As the Visio is a single thread in my c# application, all the threads follows the time slice and executes. Where it takes lots of time

My Program interacts with Visio as follows

1. Collects the objects and adds to Objects array with location of XY

2. DropMany to drop all the objects

3. Run through all the objects and edit the text to name each object droped using id Array

4. Run the connections sub routin

a. Check the connection of same level and create a connector and glue them with position

b. Check the source object of different level then place a new Circle Object and create connection (Check the page for existence of same type connector

c. Check the destination object as different level and place a circle Object and create a connection (Check the page for existence of same type connector

5. After placing each connection place the source port and destination port by a 1-d Shape

6. After placing all the connection run through all the shapes of the active page and and lock the text, Height and width

So this is the process i follow to reach the entire execution plan

Please let me know if you give a shortcut to avoid any of the Six steps i follow

Thanks & regard
Ashok
 
M

Mark Nelson [MS]

A visual would be really helpful here. Feel free to send me a "finished"
diagram that your code generates (remove 'online' from e-mail address). It
sounds like you are creating a lot of shapes and connections to build up
something that looks to the user like a single piece. If so, there may be
better ways of doing that, but I'd really need to see the drawing.

Another suggestion is to put timers around each of your steps. This will
tell you what to worry about and what not to worry about.

--
Mark Nelson
Microsoft Corporation

This posting is provided "AS IS" with no warranties, and confers no rights.


Ashok said:
Hi Mark

I have implemented in the same way. I have used the drop many method to
drop all the objects on the screen.
But unfortunately the situation is, After reading each connection from my
collection i will have a situation of connection to be made for a different
level object in the hierarchy. so looking at the connection i have put 2
conditions to find the object of different level is at the source of the
connection or at the end of connection.
So i place a new object and create the connection between same level
object and different level object on the same page which is represented as a
connector (with a Circle object).
This type of connections are known at runtime while reading each connection from my collection.

Then i use GlueToPos for specifying the area from where the connection
generates from the object to the object. So when the diagram is generated
finally i end up showing a single object with many ports and with their
connection as per kind of the port as input/output port.
This process of placing the connection on the left or right side of the
object and creation of different level object representing as connector is
consuming lots of time.
I tried implementing threading concept for connections but ended up seeing
the performance become worse. The reason i found behind this is, As the
Visio is a single thread in my c# application, all the threads follows the
time slice and executes. Where it takes lots of time.
My Program interacts with Visio as follows:

1. Collects the objects and adds to Objects array with location of XY.

2. DropMany to drop all the objects.

3. Run through all the objects and edit the text to name each object droped using id Array.

4. Run the connections sub routine

a. Check the connection of same level and create a connector and glue them with position.

b. Check the source object of different level then place a new Circle
Object and create connection (Check the page for existence of same type
connector)
c. Check the destination object as different level and place a circle
Object and create a connection (Check the page for existence of same type
connector)
5. After placing each connection place the source port and destination port by a 1-d Shape.

6. After placing all the connection run through all the shapes of the
active page and and lock the text, Height and width.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top