InfoPath Performance Issue

R

Ryan Jarrett

I am currently developing a largish(16 views ... 50-100 fields/view)
InfoPath form using managed code and (like a lot of other people) I am
experiencing some slow downs. On an older pc (but one that is the
minium for my client) the initial load is taking 30 seconds and
switching views about 10.

I have read some other postings on here and will start to implement
them (reduce the number of event handlers, and block onvalidate on
load).

On each field and section I have a multi-expression validation to check
if the user can see a section, see a field, and can edit a field. This
is done both by the user's permision level and by an option type the
user selects.

The security is done by section of fields so my question is would it
improve performance if I doubled up on the sections; making a read view
and a write view for each section in the view and then changing the
logic.

This would reduce the number of checks that it would have to do, but
would practically double the size of each view.

Would this actually help me? Or would it just change one performance
issue with an other?

Is there anything else you could sugguest?

Thank you
Ryan
 
G

G. Tarazi

Hi



I had all these issues with InfoPath and managed code last year, and at the
beginning of this year, some of our project's forms go up to 80 pages long
(read only forms, reports) :) , and some are just 10-20 pages, up to a 600
fields (editable forms).



Here is some of what we did to solve some of the problems :)



We reduced the xml event handlers to 2 global event handlers on the base DOM
node, one will fire before the content is edited, and another will fire
after the contents are edited.



We kept the event handlers of the buttons, our tests indicated no problems
there, you can have a 100 button on the form, and a 100 event handlers on
them, with no problems.



Now, the 2 main event handlers are calling functions based on the xpath that
is coming to the event handler, so, we check the xpath, and we call the
related function.



Today we have a framework of course, a base class with custom event
handlers, main loop in the global event handlers, etc, but that cames by
time, the main idea is just call functions from the 2 global event handlers.



We also found that the C# code by itself is extremely fast, I have tons of
calculations and if statements executed in milliseconds, but we also found
that if the event handlers are not managed properly, the entire InfoPath
form may disappear :) so just make sure you don't have infinite loops
between the C# code and the form XSL/XSF :)



On the C# code only it is ok, you will get an error message, but if they
collide with something on the XSF, there is a chance of 1 of 10 that the
entire forms disappears.



Now, about the form XSL, and XSF, anything in the XSF is extremely slow,
anything in the XSL is acceptable, or fast, so when we develop a form, we do
review these files frequently, for example, the conditional formatting goes
to the XSL, it is ok, the speed is acceptable.



But some rules are going to the xsf, then we try to find a way to convert
them to C# code, some of the things we do can become C# some not, once it is
C# (with the custom event handlers), the speed increases dramatically.



Not all the things in the xsf are slow, some of the items are fast, and
usually we delete entire sections from the xsf and test the form again,
until we catch the problem.



About the multiple views in a form, we found that if the form have one or
10, does not matter, unless that increases the size of the xsf, then the
speed goes down :)



And about large forms development, we usually split our form to sections,
(one big xsd still), and we have each section in a separate view, it makes
life much easier.



Then using an external C# code (we wrote) and a configuration file, we load
the xsf in to the memory (xml document), loop it, locate all xsl files, and
using the configuration file, we build new clean xsn file from one form, for
example, in one stage of our workflow, the form must show 10 section from
20, so there is no reason to load the end user with a form of 20 sections,
this is why we end up with 19 combinations (separate forms) pre generated
from a single form :) using our tools



Now if the form is very small, the load time is a second, if it is a bit
bigger, the maximum load time is 4.5 seconds.



Some of the large InfoPath reports will take up to 10 seconds to render on
the screen, after the acceleration, we still have some forms that are not
accelerated yet too, up to one minute to load :)



Be also careful with the replace node function on the xml dom in the C#
code, replacing large amount of nodes is very slow, it seams a dom problem,
talking about a 1 mb of xml, ironically, loading 10 mb of xml in the dom
using the dom function is extremely fast :) so the speed is different per
function.



The only problem is that solving these things takes time and resources, in
our case we are 10 developers working on the project, I don't think many
other projects can afford that :)



Good luck
 
P

Patrick Halstead [InfoPath MVP]

Great post! I particularly like your analysis of the XSF being slow. I had
not heard of that before but it makes sense. Most of our perf work centers
around minimizing the main DOM. We use secondary data sources (2DS) for
forms that require tons of the data. There is a lot of extra processing on
the main DOM than the 2DSes.

Josh Bell also gave a performance talk at TechEd recently and mentioned
about a half dozen performance tricks. I believe the PowerPoint should be
available somewhere. Maybe there is a link on MSDN.

Regards,
Patrick
http://www.infopathdev.com/
 
A

Alex [MSFT]

Here are some general suggestions on improving performance:

- Keep views from being too large or complex:
- Avoid lots of tables (data or layout) in any single view.

- You can use Master/Detail to reduce the number of controls in one
page.

- Try to use filter to filter the table rows.

- Avoid large repeating data structures that can grow to many pages.

- Avoid complex nesting of optional and repeatable sections. These are
quite complicated to layout and also can quickly cause a single view to
become very large.

- Avoid using Percentage width for your controls if your view contains lots
of nested controls. We have seen over 50% improvements by using Fixed Width.
You can apply Fix Width by resizing the control or specifying a fixed width
in the control's properties dialog.

- Be aware of exactly what your business logic does. For example,
onAfterChange can fire multiple times for a single edit.

- Rather than querying for all the data then having InfoPath just show a
small amount, refine your query and only bring the data you plan on
displaying into InfoPath.

- Only get the data you need to load the form

- don't pre-populate data sources that aren't necessary on load.

- Don't set up un-used data source

- Merge static xml data sources into one if you have multiple xml data
connections.

- Use Expression Box to display calculated value if you don't need to store
the value. If you have business logic to trigger all the calculation, please
only trigger necessary calculation. Triggering large amount of calculations
is costly.

- When using digital signatures, only digitally sign the information you
need to. Signing now takes a screenshot of the data signed and encodes it in
the form. The larger the screenshot, the larger the xml will become with the
encoded image.

- Avoid attaching large files to the form. These files are encoded in the
xml and can cause issues if they become too large. Provide links over
embedding large files if possible.

- Avoid embedding images in a form. For the same reasons as above.

Good luck,
Alex
 
R

Ryan Jarrett

Hi Guys,

Thank you for the tips. I have implemented several of them with some
good success.

I have isolated the line of code that is causing the main issue now,
but am not having much luck in solving it.

This is the code that is causing the issues:
// Get the root node
root = this.thisXDocument.DOM.selectSingleNode(
Utilities.DocumentPaths.root );
// get the existing data that will be replaced
existingData = this.thisXDocument.DOM.selectSingleNode( dataPath );
// clone the requested data
dataDetails = data.selectSingleNode( dataPath ).cloneNode( true );
// perform the replace
root.replaceChild( dataDetails, existingData );

The data node is supplied from a web service call, I have manipulated
it prior to this code block and am now trying to update the main data
source. I have also disabled the auto update. The line
root.replaceChild is taking around 12 seconds to run on my powerful dev
machines.

The data node could easily contain 200Kb or more once in production; in
my test cases its about 100-110kb.

I have one event handler, that will get call on any sub-node(from the
data node) on after change but have blocked it from executing(it would
still get called though).

I would really appreciate any other sugguestions you could provide.

Thanks
Ryan
 
G

G. Tarazi

replaceChild is the slowest XML DOM function Microsoft ever coded :) , I
managed to remove it from most of my forms, and uses it as less as possible
if necessary.



To give you an example, if you are using a data writer in C#, you may build
a document with the size of hundreds of MBs in almost no time.



Another example, use a loop to loop million times, and during the loop add a
complex calculation in C#, and run it, the CPU will calculate it in no time.



But replaceChild may take 1 minute to load a MB of information to the DOM, I
believe there is something terribly wrong there :)



Compare that to the load xml function inside the same dom, this one will
load exactly the same amount of xml in milliseconds :)



Somehow in the background, replace child is working with strings, and string
were never managed properly in the Microsoft programming world, for example,
in C#



string a = null;

start loop

a += "test";

end loop



If in a loop of a million times, will execute 1500 times slower that



TextWriter w = new StringBuilder();

start loop

w.Write("test");

w.Write("test");

end loop

w.ToString();



I guess someone forgot about that while coding MS XML :) (ok, bad joke)



Anyway replaceChild is from the MS XML 5.0, and as I can see, InfoPath is
built using it and using Internet Explorer (MSHTML.DLL I guess), and since
MSXML is slow, InfoPath seams to be slow (this is my assumption).



Anyway, as I read about MS XHML 6.0, they say that the speed is increased
there dramatically; I hope it is implemented in the core of Microsoft
InfoPath 2003 Service Pack 2, it is time to boost the performance.



But even if that happen, the HTML rendering needs a lot of work too, I hope
next year Microsoft Avalon / DirectX replaces it for good, but anyway, a lot
can be done there today, for example, the rendering of a DIV element is
slower than rendering of other HTML elements, and Microsoft is using the DIV
just every ware.



I belive InfoPath is Internet Explorer in the background, and the second one
is very slow with the rendering of the currently injected style sheet to the
DIV elements.



Maybe Microsoft should improve the style sheet too, or allows us to add our
custom style sheets (I am taking the one injected at runtime, not the one in
the xslt)



Maybe there is a reason behind all of that, but if I was at Microsoft, I
would've been doing tons of rewritings on the way the designer is producing
the xsl/html, the way xml is handled, etc.



Back to the form, in my case I am populating the main dom directly, and then
using the web services (if necessary), for the save only, and just simple
data loading.



How this is happening?



I have a page called Generate.Aspx

This page will receive parameters, like OperationId, document Key, etc.

It will build the xml of the document in runtime.

It will add the processing instructions.

It will write the entire results using the context, specifying that the
results are InfoPath/xml (mime type)

And the xml will simply execute opening the form by itself, populating the
main data source by itself.



But be careful, if you do that, you will notice that InfoPath will call
Generate.aspx 3 more times :) we call it in our team, the InfoPath 3 times
loading bug :)



To avoid overloading our server farm, we use 15 seconds caching of the
generated document back to the SQL servers :)



All of that code was written, just to avoid the replaceChild :)



This is why sometimes I do complain to Microsoft, "do less with more",
again, another bad joke, sorry :)



Good luck
 
R

Ryan Jarrett

Thanks for the reply.

I actually did a previous project in the manor in which you described.
Except I used an HttpHandler. I didn't have the issue with InfoPath
calling it 3 times though.

I would have done this project in a simialar manor, but the client does
not want a web interface.

When the user opens the form, they perform a few actions via custom
task panes ( login (https web service), perform a search or two) and
then request the required form from a taskpane.

I would only add the follow to your request of the next release; if you
make custom changes to the xsl's that they don't change them back to
the defaults if you edit it in the designer (like they have done in the
new release of Visual Studio).

Thanks for all the help!
 

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