New Posts New Posts RSS Feed: Any idea about speeding up the load time of a form?
  FAQ FAQ  Forum Search   Calendar   Register Register  Login Login

Any idea about speeding up the load time of a form?

 Post Reply Post Reply
Author
HFloyd View Drop Down
Groupie
Groupie


Joined: 27-Jul-2007
Location: United States
Posts: 44
Post Options Post Options   Quote HFloyd Quote  Post ReplyReply Direct Link To This Post Topic: Any idea about speeding up the load time of a form?
    Posted: 09-Jan-2009 at 12:04pm
In my application, I have noticed that certain forms take quite awhile to display the first time during an application session, but then act responsively when the same form is requested later in the session. Of course, after the application is shut down and re-opened, it again takes a very long time to display the form.

For instance, I have a "Transactions" Form, which takes an unimaginably long time to display (nearly 10 minutes), and when I check the debuglog, it lists 2000 lines of database queries:

RdbKey: [default] Sql: select * from "dbo"."FinancialTransaction"
RdbKey: [default] Sql: select * from "dbo"."TransactionLineItem" where ((1 = 0))
RdbKey: [default] Sql: select * from "dbo"."TransactionLineItem" where ("dbo"."TransactionLineItem"."TransactionREF" in (?)) Params: v0=00165662-a9be-4900-84eb-3b2ee391349e
RdbKey: [default] Sql: select * from "dbo"."EventTicketSale" where ((1 = 0))
RdbKey: [default] Sql: select * from "dbo"."EventTicketSale" where ("dbo"."EventTicketSale"."TransactionLineItemREF" in (?)) Params: v0=56e4a6d4-a73f-4a1d-8eb8-459b098f6877
RdbKey: [default] Sql: select * from "dbo"."Payment" where ((1 = 0))
RdbKey: [default] Sql: select * from "dbo"."Payment" where ("dbo"."Payment"."TransactionREF" in (?)) Params: v0=00165662-a9be-4900-84eb-3b2ee391349e
RdbKey: [default] Sql: select * from "dbo"."HouseholdBusiness" where ((1 = 0))
RdbKey: [default] Sql: select * from "dbo"."HouseholdBusiness" where ("dbo"."HouseholdBusiness"."HouseholdBusinessGUID"=?) Params: v0=dfecf0d1-84f8-470a-97d6-e1c6ae121c07
RdbKey: [default] Sql: select * from "dbo"."TransactionLineItem" where ("dbo"."TransactionLineItem"."TransactionREF" in (?)) Params: v0=8253ad0f-a3a0-44a3-ae56-7214fd358cfb
RdbKey: [default] Sql: select * from "dbo"."TransactionLineItem" where ("dbo"."TransactionLineItem"."TransactionREF" in (?)) Params: v0=ffa1380b-c33f-46ea-8d28-4a528865e113
RdbKey: [default] Sql: select * from "dbo"."HouseholdBusiness" where ("dbo"."HouseholdBusiness"."HouseholdBusinessGUID"=?) Params: v0=48f53d40-1eff-4a5f-9788-18e9246dc5f9
RdbKey: [default] Sql: select * from "dbo"."TransactionLineItem" where ("dbo"."TransactionLineItem"."TransactionREF" in (?)) Params: v0=0018c8c4-b615-4c6e-9120-167fd8dc369c
RdbKey: [default] Sql: select * from "dbo"."HouseholdBusiness" where ("dbo"."HouseholdBusiness"."HouseholdBusinessGUID"=?) Params: v0=bcddfc9d-6fc1-4a62-a72c-ca92f7e85219


Does anyone have any insight into this? Specifically, I would love to know if there is some way I can speed up the form display and possible "pre-load" the form (on a different thread) when the application starts, so when the user requests the form, it displays quickly.

Right now I have this code running in the Shell application (on app start):
(entityTypes is a list of a few of the entity types in my application which seem to be the slow-loading form entities)


/// <summary>Get all Entities of Types in a list into the PM asynchronously</summary>
        /// <param name="entityType">The list of Types to get entities of</param>
        public static void GetDataAsync(IEnumerable<Type> entityTypes)
        {
            string TypeName;
            string Token;

            foreach (Type type in entityTypes)
            {
                TypeName = type.Name;
                Token = TypeName + "_Complete";

                RdbQuery ASQuery = new RdbQuery(type);

                MainPm.Manager.GetEntitiesAsync(ASQuery, QueryStrategy.Normal, Token);

                DebugFns.WriteLine("FI_CODE: GetDataAsync() " + TypeName + " Completed (" + Token + ")");
            }
        }


Is there something else I should be doing?

Thanks in advance!

Heather


Edited by HFloyd - 09-Jan-2009 at 12:48pm
Back to Top
davidklitzke View Drop Down
IdeaBlade
IdeaBlade
Avatar

Joined: 14-Jun-2007
Posts: 715
Post Options Post Options   Quote davidklitzke Quote  Post ReplyReply Direct Link To This Post Posted: 12-Jan-2009 at 4:31pm
Heather,
 
Just getting the data asynchronously may not help very much if your first asynchronous request gets a lot of data from the database (or too little data).  Try to get enough data on your first request so that you can make an initial display of the form, then in your background thread, you can ask for more data.
 
I would also consider using paged queries, and a paged form.
 
David
Back to Top
HFloyd View Drop Down
Groupie
Groupie


Joined: 27-Jul-2007
Location: United States
Posts: 44
Post Options Post Options   Quote HFloyd Quote  Post ReplyReply Direct Link To This Post Posted: 14-Jan-2009 at 6:08pm
Thanks for the ideas, David. I am investigating the "paged queries".

How I have it set up now is that on application open, I have async queries running that pull data from all the tables into the cache. The user interface of the application appears in a reasonable amount of time for "application boot" (the initial "home" screen doesn't contain any data for display), but when the user then clicks to one of the main forms (which holds all the people and addresses, etc. in the database (11K records), it takes a very long time to load, or seems to hang completely.

The user might want to look up any person in the system, so I'm not sure about how paging would work (they use a lookup combo box to select a person to "jump" to, generally, though the form also has a DataNavigator control).

I have looked at the sample code on Paging: http://www.ideablade.com/forum/forum_posts.asp?TID=40 but am unclear about the best way to implement it in my user interface....

Currently this is how I set up the form:

private void HouseholdsBusinesses_Load(object sender, EventArgs e)
        {
            //Data
            base.InitalizePM();
            ConfigureBindingSources();
            LoadData();
           ....other basic form setup code...
}

        public override void ConfigureBindingSources()
        {
            //Binding Sources - Main
            this.bsMainEntity.DataSource = mListMainEntity;
            this.bsMainFilter.DataSource = mListFilterLookup;

            //Binding Sources - Lookup Lists
            this.bsUseSalutationTypes.DataSource = mListUseSalutationTypes;
            this.bsUseFullNamesTypes.DataSource = mListUseFullnameTypes;
            this.bsHBType.DataSource = mListHBTypes;
            this.bsReferredByPeople.DataSource = mListReferredByPeople;
            this.bsRelationshipSourceType.DataSource = mListRelationshipSource;
            this.bsCountries.DataSource = mListCountries;
            this.bsAuctionYears.DataSource = mListAuctionYears;
            this.bsContactMethodTypes.DataSource = mListContactMethodTypes;
           
            //Data Navigator
            this.MainDataNavigator.DataSource = bsMainEntity;
        }

public override void LoadData()
        {
            //Main Lists
            mListMainEntity.ReplaceRange(mPersMgr.GetEntities<HouseholdBusiness>());
            mListMainEntity.ApplySort(
                               EntityPropertyDescriptors.HouseholdBusiness.DefaultSort,
                               ListSortDirection.Ascending);
 
            mListFilterLookup.ReplaceRange(mPersMgr.GetEntities<HouseholdBusiness>());
            mListFilterLookup.ApplySort(
                               EntityPropertyDescriptors.HouseholdBusiness.DefaultSort,
                               ListSortDirection.Ascending);
 
            //Lookup Lists
            mListHBTypes.ReplaceRange(mPersMgr.GetEntities<HBType>());
           
            mListReferredByPeople.ReplaceRange(mPersMgr.GetEntities<Person>());
            mListReferredByPeople.ApplySort(
                               EntityPropertyDescriptors.Person.DefaultSort,
                               ListSortDirection.Ascending);

            mListRelationshipSource.ReplaceRange(mPersMgr.GetEntities<RelationshipSource>());
            mListRelationshipSource.ApplySort(
                               EntityPropertyDescriptors.RelationshipSource.DefaultSort,
                               ListSortDirection.Ascending);

            mListCountries.ReplaceRange(mPersMgr.GetEntities<Country>());
            mListCountries.ApplySort(
                               EntityPropertyDescriptors.Country.DefaultSort,
                               ListSortDirection.Ascending);

            mListAuctionYears.ReplaceRange(mPersMgr.GetEntities<AuctionYear>());
            mListAuctionYears.ApplySort(
                               EntityPropertyDescriptors.AuctionYear.DefaultSort,
                               ListSortDirection.Ascending);

            mListContactMethodTypes.ReplaceRange(mPersMgr.GetEntities<ContactMethodType>());
            mListContactMethodTypes.ApplySort(
                               EntityPropertyDescriptors.ContactMethodType.DefaultSort,
                               ListSortDirection.Ascending);

            mListUseSalutationTypes.ReplaceRange(mPersMgr.GetEntities<UseSalutationType>());
            mListUseSalutationTypes.ApplySort(
                               EntityPropertyDescriptors.UseSalutationType.USTOrderNum,
                               ListSortDirection.Ascending);

            mListUseFullnameTypes.ReplaceRange(mPersMgr.GetEntities<UseFullNamesType>());
            mListUseFullnameTypes.ApplySort(
                               EntityPropertyDescriptors.UseFullNamesType.UFTOrderNum,
                               ListSortDirection.Ascending);
        }


I tried to alter LoadData() like this:

    //Main Lists
            // Query orders in ascending HBName  sequence.
            RdbQuery aQuery = new RdbQuery(typeof(HouseholdBusiness));
            aQuery.AddOrderBy(HouseholdBusiness.HBNameEntityColumn, ListSortDirection.Ascending);

            // Build a paged query to retrieve 10 items at a time.
            PagedRdbQuery pagedQuery = new PagedRdbQuery(aQuery);
            pagedQuery.PageSize = 10;

            // Specify whether the last item of the page will be first item on next page.
            pagedQuery.PagesShouldOverlap = false;
                       
        while (true)
        {
                mListMainEntity.ReplaceRange(mPersMgr.GetEntities<HouseholdBusiness>(pagedQuery));
                DebugFns.WriteLine("Current page = " + pagedQuery.CurrentPage.ToString());
                DebugFns.WriteLine("Count for this page = " + mListMainEntity.Count.ToString());

                if (pagedQuery.IsLastPage) break;

                // Advance the query.
                pagedQuery.NextPage();
        }
...


but it took just as long (or possibly longer...) with no quicker form display, and once the form DID display - it was totally empty of data. I must be missing something very basic here...

I also was experiementing with running the query async...

mListMainEntity.ReplaceRange(mPersMgr.GetEntitiesAsync<HouseholdBusiness>(aQuery, QueryStrategy.Normal, "HB_Paged"));

but that won't compile...

I don't mind if the records take some time to load into the system, but I'd really like to have the form display with SOMETHING as soon as possible, and still have all the data loading in for access.

If someone could point out how I am not understanding this, or provide some code samples I would be grateful.

Thanks,
Heather




Edited by HFloyd - 15-Jan-2009 at 7:51am
Back to Top
davidklitzke View Drop Down
IdeaBlade
IdeaBlade
Avatar

Joined: 14-Jun-2007
Posts: 715
Post Options Post Options   Quote davidklitzke Quote  Post ReplyReply Direct Link To This Post Posted: 15-Jan-2009 at 4:43pm
Heather,
 
Continue to work on thr paging example.  I am sire that you will eventually "get it".
 
Also, work through the Asynch Query examples in the Tutorials until you understand why this helps performance.
 
Maybe, your problem is that you just have too much data.  Is there any way to make the amount of data smaller.  For example, can you have your user choose (to begin with) "This Year's Customers" and "Last Year's Customers", or "Customers from New York" and "Customers from New Jersey".  Look at some examples of our QBE Control where an initial control narrows the number of items that will be included.
 
You say that "The user might want to look up any person in the system, so I'm not sure about how paging would work".
 
You have a choice.  You can try to display a list of all the customers and then have your user "page" or "scroll" that list, or you can start with a "search" function (or both).  If you don't have to build a large list and can just "search", that is the fastest, but probably, you want your user to be able to page though a large list.
 
Another advanced techniaue you might consider is to use a "Dynamic Entity".  For example, get just the First Name and Last Name of each customer, and construct a Dynamic Entity that just has these two columns.  and so you would just be retrieving two columns of each row.  That would make the retrieval from the database faster. Display a list of these Dynamic Entities.  When the user clicks on the Customer, you could retrieve the record with all columns.
 
David
Back to Top
HFloyd View Drop Down
Groupie
Groupie


Joined: 27-Jul-2007
Location: United States
Posts: 44
Post Options Post Options   Quote HFloyd Quote  Post ReplyReply Direct Link To This Post Posted: 02-Feb-2009 at 7:43pm
Hi David.

As per Greg's instructions - http://www.ideablade.com/forum/forum_posts.asp?TID=261
I have sent a request to support for the QBE code...

Heather
Back to Top
HFloyd View Drop Down
Groupie
Groupie


Joined: 27-Jul-2007
Location: United States
Posts: 44
Post Options Post Options   Quote HFloyd Quote  Post ReplyReply Direct Link To This Post Posted: 30-Jun-2009 at 1:32pm
Believe it or not, I am still working on improving the load time of my forms.

I have been able to make some progress - I added a quick "Search" box to the top of the form, so the underlying data is not loaded until the user types in part of a name to search on. After clicking a "Get Records" button, an RDB query retrieves only the few records which match that search term, then the user can click through that smaller result-set. This is working pretty well, and the record retrieval is fairly quick.

However, I noticed that some of the combo boxes on my form still require a large number of records to be retrieved. For instance, I have an Entity called "Household" and that is related to an entity called "Person" in a 1-many relationship. If I am on the "people" form, there is a combo box indicating which Household that person belongs to. The box needs to have a list of all the available households, and should be displaying the current linked household name in the combo box on the form.

I found that as long as I am calling the database to fill a list for that combo-box, the load time of the form is still very long. On Form_Load I have it pull in the lookup list data:

//Lookup Lists
             mListInvolvementType.ReplaceRange(mPersMgr.GetEntities<InvolvementType>());
             mListInvolvementType.ApplySort(
                                EntityPropertyDescriptors.InvolvementType.DefaultSort,
                                ListSortDirection.Ascending);

             mListHouseholdBusiness.ReplaceRange(mPersMgr.GetEntities<HouseholdBusiness>());
             mListHouseholdBusiness.ApplySort(
                                EntityPropertyDescriptors.HouseholdBusiness.DefaultSort,
                                ListSortDirection.Ascending);



Since the Household lookup list only needs a few columns - the GUID and some display properties, I thought I would create a separate entity type which would only get those few necessary columns to be used as the source of the look-up list, and load those instead:

             ...
             mListHouseholdBusiness.ReplaceRange(mPersMgr.GetEntities<HouseholdBusiness_Lookup>());
             mListHouseholdBusiness.ApplySort(
                                EntityPropertyDescriptors.HouseholdBusiness_Lookup.DefaultSort,
                                ListSortDirection.Ascending);


Which does somewhat reduce the load time, but the combo-box on the form does not display the currently linked Household. I shows as blank, witht he ability to select from the "HouseholdBusiness_Lookup" list.

Perhaps it is treating the relationship between "Person" and "HouseholdBusiness_Lookup" as different from the relationship between "Person" and "HouseholdBusiness" because they are different entities - even though the same database relationship is used to define them?

Am I going about this wrong - or will I need to load int he regular "HouseholdBusiness" entity to fill the look-up list?

Back to Top
GregD View Drop Down
IdeaBlade
IdeaBlade
Avatar

Joined: 09-May-2007
Posts: 374
Post Options Post Options   Quote GregD Quote  Post ReplyReply Direct Link To This Post Posted: 02-Jul-2009 at 12:46pm
Try displaying the HouseholdBusiness_Lookup relation property of the Person in the ComboBox, instead of the Household. Then, in a custom setter for HouseholdBusiness_Lookup, also set the Household.

Back to Top
HFloyd View Drop Down
Groupie
Groupie


Joined: 27-Jul-2007
Location: United States
Posts: 44
Post Options Post Options   Quote HFloyd Quote  Post ReplyReply Direct Link To This Post Posted: 02-Jul-2009 at 3:04pm
Thanks for your reply, Greg.

I actually decided that the overhead to load in all the possible objects (even if they were "smaller") was still too much, so I am removing the drop-down from the main form and instead having a button to "Change..." which will bring up a pop-up form to choose the new Household. This will limit the data loading to happen only when requested by the user (which, in reality, won't be that often).

There are really only 2 entities which are this unwieldy, so implementing the dialog box shouldn't be too onerous.


Heather
Back to Top
 Post Reply Post Reply

Forum Jump Forum Permissions View Drop Down