Slowness in Custom Field Lookup/Outline Code structure access

S

SunGard

First of all, my question: Is this really supposed to be this slow?

Now to the story:

In order to create a custom field editor form, I need to get all lookup
table entries for each field. There are approximately 64 outline codes (for
each oc) in the loop below. The loop below takes more than 2.5 seconds (after
I've stripped everything out of it):

' --- Code Begin
For Each oc As Microsoft.Office.Interop.MSProject.OutlineCode In
Globals.ThisAddIn.Application.GlobalOutlineCodes
For Each ltEntry As
Microsoft.Office.Interop.MSProject.LookupTableEntry In oc.LookupTable

Next ltEntry
Next
' --- Code End

The total iterations of inner/outer loops is around 800. So, the user is
waiting for 2.5 seconds just to get the lookup table values organized. In
order to add these values into a dictionary for final use by a ComboBox, I
instantiate a "ValueDescriptionPair" using the following class which is as
simple as you can get:

' --- Code Begin
Public Class ValueDescriptionPair
Private m_Value As String
Private m_Description As String

Public ReadOnly Property Value() As String
Get
Return m_Value
End Get
End Property

Public ReadOnly Property Description() As String
Get
Return m_Description
End Get
End Property

Public Sub New(ByRef NewValue As String, ByRef NewDescription As
String)
m_Value = NewValue
m_Description = NewDescription
End Sub

Public Overrides Function ToString() As String
Return m_Description
End Function
End Class
' --- Code End

So, including the list building, the following code takes 6.96 seconds. This
is a long time for the user to wait:

' --- Code Begin
Dim vdp As ValueDescriptionPair = Nothing
' Add lookup tables into a dictionary for ease of search
For Each oc As Microsoft.Office.Interop.MSProject.OutlineCode In
Globals.ThisAddIn.Application.GlobalOutlineCodes
Try
' Hold list of items for eventual use by the combo box
Dim ItemObject(oc.LookupTable.Count - 1) As System.Object

i = 0
For Each ltEntry As
Microsoft.Office.Interop.MSProject.LookupTableEntry In oc.LookupTable

vdp = New ValueDescriptionPair(ltEntry.FullName,
ltEntry.FullName)
ItemObject(i) = vdp
i = i + 1
Next ltEntry

Catch ex As Exception
MsgBox("getProjectServerData: Error in populating
dictionary: " & ex.Message())
End Try
Next
' --- Code End

The above code doesn't even include adding the list to the dictionary. It is
almost unacceptable to the Users for this wait. The final code takes more
than 9 seconds to build the list, and popup the form. on second press, I use
the dictionary and it takes 1 to 2 seconds as I've created my own cache.

My question is: Is this really supposed to be this slow?

Just an empty loop is taking 2.5 seconds which is a bit baffling to me.
Instantiating a simple (class) structure for each entry adds more than 4.5
seconds.

Please give me advice - maybe I am doing something in VBA inefficiently?

Thank you!
 
R

Rod Gill

As it happens, I'm learning the ins and outs of VSTO for my updated book so
I did a test. Firstly, your code is VB.Net in Visual Studio for Office
(VSTO) right?

I created a new project and added 10 lookup fields to outlinecode1. I then
ran this code:

Sub TestOutlineCodeLookup()
Dim oc As OutlineCode
Dim Lte As LookupTableEntry
Dim str As String
Dim tim As Single
Dim sng As Single
tim = Timer
For Each oc In ActiveProject.OutlineCodes
For Each Lte In oc.LookupTable
str = str & Lte.Name & ", "
Next
Next
sng = Round(Timer - tim, 4)
MsgBox str & vbCrLf & "Time = " & sng & " seconds", vbInformation +
vbOKOnly
End Sub

So, looking up entries in Project staying within the project process (which
is what VBA does and why it's so surprisingly fast) is not a problem. 10
entries in about.012 seconds is OK.

I suspect you are suffering from the old inter-process road blocks that make
reading a datum in one process from another so slow.

What would make it much faster is adding a VBA macro into the Enterprise
global to do all the reading and then pass it back. 1 inter-process get for
each Outlook code or maybe all of them?


--

Rod Gill
Microsoft MVP for Project

Author of the only book on Project VBA, see:
http://www.projectvbabook.com




SunGard said:
First of all, my question: Is this really supposed to be this slow?

Now to the story:

In order to create a custom field editor form, I need to get all lookup
table entries for each field. There are approximately 64 outline codes
(for
each oc) in the loop below. The loop below takes more than 2.5 seconds
(after
I've stripped everything out of it):

' --- Code Begin
For Each oc As Microsoft.Office.Interop.MSProject.OutlineCode
In
Globals.ThisAddIn.Application.GlobalOutlineCodes
For Each ltEntry As
Microsoft.Office.Interop.MSProject.LookupTableEntry In oc.LookupTable

Next ltEntry
Next
' --- Code End

The total iterations of inner/outer loops is around 800. So, the user is
waiting for 2.5 seconds just to get the lookup table values organized. In
order to add these values into a dictionary for final use by a ComboBox, I
instantiate a "ValueDescriptionPair" using the following class which is as
simple as you can get:

' --- Code Begin
Public Class ValueDescriptionPair
Private m_Value As String
Private m_Description As String

Public ReadOnly Property Value() As String
Get
Return m_Value
End Get
End Property

Public ReadOnly Property Description() As String
Get
Return m_Description
End Get
End Property

Public Sub New(ByRef NewValue As String, ByRef NewDescription
As
String)
m_Value = NewValue
m_Description = NewDescription
End Sub

Public Overrides Function ToString() As String
Return m_Description
End Function
End Class
' --- Code End

So, including the list building, the following code takes 6.96 seconds.
This
is a long time for the user to wait:

' --- Code Begin
Dim vdp As ValueDescriptionPair = Nothing
' Add lookup tables into a dictionary for ease of search
For Each oc As Microsoft.Office.Interop.MSProject.OutlineCode
In
Globals.ThisAddIn.Application.GlobalOutlineCodes
Try
' Hold list of items for eventual use by the combo box
Dim ItemObject(oc.LookupTable.Count - 1) As
System.Object

i = 0
For Each ltEntry As
Microsoft.Office.Interop.MSProject.LookupTableEntry In oc.LookupTable

vdp = New ValueDescriptionPair(ltEntry.FullName,
ltEntry.FullName)
ItemObject(i) = vdp
i = i + 1
Next ltEntry

Catch ex As Exception
MsgBox("getProjectServerData: Error in populating
dictionary: " & ex.Message())
End Try
Next
' --- Code End

The above code doesn't even include adding the list to the dictionary. It
is
almost unacceptable to the Users for this wait. The final code takes more
than 9 seconds to build the list, and popup the form. on second press, I
use
the dictionary and it takes 1 to 2 seconds as I've created my own cache.

My question is: Is this really supposed to be this slow?

Just an empty loop is taking 2.5 seconds which is a bit baffling to me.
Instantiating a simple (class) structure for each entry adds more than 4.5
seconds.

Please give me advice - maybe I am doing something in VBA inefficiently?

Thank you!

--
Sungard Microsoft Products Development Team

__________ Information from ESET Smart Security, version of virus
signature database 4553 (20091028) __________

The message was checked by ESET Smart Security.

http://www.eset.com

__________ Information from ESET Smart Security, version of virus signature database 4553 (20091028) __________

The message was checked by ESET Smart Security.

http://www.eset.com
 
S

SunGard

Hi Rod,

Thank you for your time and trial on the code!

Our situation is that we have about 64 outline codes and some Lookup Tables
can have many tens of items long. The total inner loop count in our case is
around 800.

In our production environment, it takes 41 seconds to go through the full
loop (including the instantiation of the ValueDescriptionPair object). In
UAT, it takes 9 seconds.

We found that the Prod environment has a lookup table that has 300 items in
it. So it is really related to the sizes.

Is it possible (relatively easy) for you to create a bunch more outline
codes and try your code? (only if you have time and I thank you for your time
so far).

I am going to take your code and try it out myself as well. I'll report the
results here.

Thanks for your feedback!
 
R

Rod Gill

Increasing the number won't make any difference. It's about 0.001 sec per
item so 800 is 0.8 seconds. The problem is in using an add-in to make
multiple reads from Project. That's why I suggested the add-in calls a macro
to do the reading and send back far fewer strings. In fact one call to a
macro and a string array returned with 800 elements should only take 1
second or so.

--

Rod Gill
Microsoft MVP for Project

Author of the only book on Project VBA, see:
http://www.projectvbabook.com




SunGard said:
Hi Rod,

Thank you for your time and trial on the code!

Our situation is that we have about 64 outline codes and some Lookup
Tables
can have many tens of items long. The total inner loop count in our case
is
around 800.

In our production environment, it takes 41 seconds to go through the full
loop (including the instantiation of the ValueDescriptionPair object). In
UAT, it takes 9 seconds.

We found that the Prod environment has a lookup table that has 300 items
in
it. So it is really related to the sizes.

Is it possible (relatively easy) for you to create a bunch more outline
codes and try your code? (only if you have time and I thank you for your
time
so far).

I am going to take your code and try it out myself as well. I'll report
the
results here.

Thanks for your feedback!

--
Sungard Microsoft Products Development Team




__________ Information from ESET Smart Security, version of virus
signature database 4553 (20091028) __________

The message was checked by ESET Smart Security.

http://www.eset.com

__________ Information from ESET Smart Security, version of virus signature database 4553 (20091028) __________

The message was checked by ESET Smart Security.

http://www.eset.com
 
S

SunGard

Rod,

I am trying various things with that code now.

But here is the real kicker –

Globals.ThisAddIn.Application.ActiveProject.OutlineCodes is empty!

While:
Microsoft.Office.Interop.MSProject.OutlineCode has all the values

We are using Project Server and so the outline codes seem to be populated
into the "Microsoft.Office.Interop.MSProject.OutlineCode" structure.

I'll continue investigating other ways....

Thanks for the help though!
 
S

SunGard

Rod,

The real issue is that you are accessing "local" outline codes (which are
empty in our case). We are using
"Globals.ThisAddIn.Application.GlobalOutlineCodes". So whether there is
interprocess communication or not - the collection you are using for testing
is different. Yes, it is fast for us too - but the loop is empty!

Globals.ThisAddIn.Application.ActiveProject.OutlineCodes is empty!

While:

Globals.ThisAddIn.Application.GlobalOutlineCodes has all the values

We are using Project Server and so the outline codes seem to be populated
into the "Globals.ThisAddIn.Application.GlobalOutlineCodes" structure.

Thanks in any case.
 
R

Rod Gill

I don't have a Project Server instance to play with at the moment, hence the
use of local Outline codes. I would expect next to no difference with Global
Outline codes however as they are cached locally.

--

Rod Gill
Microsoft MVP for Project

Author of the only book on Project VBA, see:
http://www.projectvbabook.com




SunGard said:
Rod,

I am trying various things with that code now.

But here is the real kicker –

Globals.ThisAddIn.Application.ActiveProject.OutlineCodes is empty!

While:
Microsoft.Office.Interop.MSProject.OutlineCode has all the values

We are using Project Server and so the outline codes seem to be populated
into the "Microsoft.Office.Interop.MSProject.OutlineCode" structure.

I'll continue investigating other ways....

Thanks for the help though!

--
Sungard Microsoft Products Development Team




__________ Information from ESET Smart Security, version of virus
signature database 4553 (20091028) __________

The message was checked by ESET Smart Security.

http://www.eset.com

__________ Information from ESET Smart Security, version of virus signature database 4553 (20091028) __________

The message was checked by ESET Smart Security.

http://www.eset.com
 

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