List performance latest EPC
List performance latest EPC
After installing EPC 141011, 141031, and 141050 I recompiled all web components. We have a VL-WEB app that shows registrations to an event. The default is to show all events, and we mark them all as selected, so when the page loads there are 1650 rows in the List view.
Performance is OK loading the initial view. But if the user simply clicks on one of the entries, there can be 5+ second delay while the browser is unresponsive. All selections after are instant. This happens no matter how many entries are on the list. I think this has to do with all of the entries being selected = true.
When the user makes selections around the list, we want to update counters. We have 3 values displayed, total number of registrations, selected registrations, and number of attendees. On the itemgotselection event, we selectlist/endSelect and update our counters. This performs OK.
Thanks for any suggestions, Art
Performance is OK loading the initial view. But if the user simply clicks on one of the entries, there can be 5+ second delay while the browser is unresponsive. All selections after are instant. This happens no matter how many entries are on the list. I think this has to do with all of the entries being selected = true.
When the user makes selections around the list, we want to update counters. We have 3 values displayed, total number of registrations, selected registrations, and number of attendees. On the itemgotselection event, we selectlist/endSelect and update our counters. This performs OK.
Thanks for any suggestions, Art
Art Tostaine
- Stewart Marshall
- Posts: 417
- Joined: Thu Nov 05, 2015 5:25 pm
Re: List performance latest EPC
Hi Art
If you're updating on ItemGotSelection, I'm going to assume that you're doing the same on ItemLostSelection too. This will mean that a single click will cause 1649 events to fire if everything is selected. This will read all 1650 records each time, mapping list items to field values and updating the counters and so on.
Better here would be the For command which only looks at the visual items, so it's far quicker. However, it's really the 1600+ events that are the problem. Fortunately, this is simple to avoid.
In practice, you only need to update the counter when the user finishes (de)selecting things. This is best done by starting a short interval timer that continually stops and starts when an event fires. If they happen in quick succession, the timer resets, so no calculations are done. When the events stop, the timer ticks and you can update the counters.
The use of timers in this way is an important technique for managing activities that will cause many events to fire. e.g. A Changed event on an edit might run some processing. OK if the user is as rubbish at typing as I am, but not so good when a key is held down and the key rapidly repeats (e.g. Backspacing).
If you're updating on ItemGotSelection, I'm going to assume that you're doing the same on ItemLostSelection too. This will mean that a single click will cause 1649 events to fire if everything is selected. This will read all 1650 records each time, mapping list items to field values and updating the counters and so on.
Better here would be the For command which only looks at the visual items, so it's far quicker. However, it's really the 1600+ events that are the problem. Fortunately, this is simple to avoid.
In practice, you only need to update the counter when the user finishes (de)selecting things. This is best done by starting a short interval timer that continually stops and starts when an event fires. If they happen in quick succession, the timer resets, so no calculations are done. When the events stop, the timer ticks and you can update the counters.
The use of timers in this way is an important technique for managing activities that will cause many events to fire. e.g. A Changed event on an edit might run some processing. OK if the user is as rubbish at typing as I am, but not so good when a key is held down and the key rapidly repeats (e.g. Backspacing).
Code: Select all
Begin_Com Role(*EXTENDS #PRIM_WEB) Height(545) Width(905) Theme(#SYS_THEME<2015Blue>) LayoutManager(#Layout1)
Define_Com Class(#PRIM_TBLO) Name(#Layout1)
Define_Com Class(#PRIM_TBLO.Column) Name(#Column1) DisplayPosition(1) Parent(#Layout1)
Define_Com Class(#PRIM_TBLO.Row) Name(#Row1) DisplayPosition(1) Parent(#Layout1) Height(82) Units(Pixels)
Define_Com Class(#PRIM_TBLO.Row) Name(#Row2) DisplayPosition(2) Parent(#Layout1) Height(1.7)
Define_Com Class(#PRIM_TBLO.Item) Name(#LayoutItem2) Alignment(TopLeft) Column(#Column1) Manage(#Selected) Parent(#Layout1) Row(#Row1) Sizing(None) MarginLeft(8) MarginTop(8) Flow(Down)
Define_Com Class(#PRIM_TBLO.Item) Name(#LayoutItem1) Column(#Column1) Manage(#List) Parent(#Layout1) Row(#Row2)
Define_Com Class(#xDemoNumber.Visual) Name(#Selected) DisplayPosition(1) Parent(#COM_OWNER) TabPosition(1) Left(8) Top(8) Height(25) Caption('Selected') LabelType(Caption) DisplayOnly(True)
Define_Com Class(#PRIM_LIST) Name(#List) DisplayPosition(2) Left(0) Parent(#COM_OWNER) TabPosition(2) Top(82) Height(463) Width(905) SelectionStyle(All)
Define_Com Class(#PRIM_LIST.String) Name(#ColumnXEMPLOYID1) ColumnWidth(92) DisplayPosition(1) Parent(#List) Source(#xEmployeeIdentification)
Define_Com Class(#PRIM_LIST.String) Name(#ColumnXEMPTITLE1) ColumnWidth(167) DisplayPosition(2) Parent(#List) Source(#xEmployeeTitle)
Define_Com Class(#PRIM_LIST.String) Name(#ColumnXSURNAME1) ColumnWidth(239) DisplayPosition(3) Parent(#List) Source(#xEmployeeSurname)
Define_Com Class(#PRIM_LIST.String) Name(#ColumnXGIVENAME1) ColumnWidth(152) DisplayPosition(4) Parent(#List) Source(#xEmployeeGivenNames)
Define_Com Class(#PRIM_LIST.DateTime) Name(#ColumnXEMPDOB1) ColumnWidth(99) DisplayPosition(5) Parent(#List) ShowTime(False) Source(#xEmployeeDateofBirth)
Define_Com Class(#PRIM_LIST.String) Name(#ColumnXGENDER1) ColumnWidth(90) DisplayPosition(6) Parent(#List) Source(#xEmployeeGender)
Define_Com Class(#PRIM_LIST.String) Name(#ColumnXSTREET1) ColumnWidth(307) DisplayPosition(7) Parent(#List) Source(#xEmployeeStreet)
Define_Com Class(#PRIM_LIST.String) Name(#ColumnXCITY1) ColumnWidth(307) DisplayPosition(8) Parent(#List) Source(#xEmployeeCity)
Define_Com Class(#PRIM_LIST.String) Name(#ColumnXSTATE1) ColumnWidth(307) DisplayPosition(9) Parent(#List) Source(#xEmployeeState)
Define_Com Class(#PRIM_LIST.String) Name(#ColumnXPOSTCODE1) ColumnWidth(96) DisplayPosition(10) Parent(#List) Source(#xEmployeePostalCode)
Define_Com Class(#PRIM_PHBN) Name(#SelectAll) Caption('SelectAll') DisplayPosition(3) Left(318) Parent(#COM_OWNER) TabPosition(3) Top(15) Width(123)
Def_List Name(#Employees) Fields(#xEmployeeIdentification #xEmployeeTitle #xEmployeeSurname #xEmployeeGivenNames #xEmployeeDateofBirth #xEmployeeGender #xEmployeeStreet #xEmployeeCity #xEmployeeState #xEmployeePostalCode #xEmployeeCountry #xEmployeeHomeTelephone #xEmployeeBusinessTelephone #xEmployeeMobilePhone #xEmployeeSalary #xEmployeeStartDate #xEmployeeTerminationDate #xDepartmentCode #xEmployeeImageThumbnail) Counter(#Listcount) Type(*Working) Entrys(*Max)
Define_Com Class(#prim_timr) Name(#SelectionTimer) Interval(50) Startup(Manual)
Evtroutine Handling(#Com_owner.CreateInstance)
#Com_owner.Load
Endroutine
Mthroutine Name(Load)
Define_Com Class(#xDemoWebDataServices.GetEmployees) Name(#GetEmployees)
#GetEmployees.ExecuteAsync( #Employees )
Evtroutine Handling(#GetEmployees.Completed)
Begin_Loop To(50)
Selectlist Named(#Employees)
Add_Entry To_List(#List)
Endselect
End_Loop
Endroutine
Endroutine
Evtroutine Handling(#SelectAll.Click)
#List.Items<>.Selected := True
#Com_owner.GetSelected
Endroutine
Evtroutine Handling(#List.ItemGotSelection #List.ItemLostSelection)
#Com_owner.GetSelected
Endroutine
Mthroutine Name(GetSelected)
#SelectionTimer.Stop
#SelectionTimer.Start
Endroutine
Evtroutine Handling(#SelectionTimer.Tick)
Define_Com Class(#Prim_nmbr) Name(#SelectedRows)
#SelectionTimer.Stop
For Each(#Item) In(#List.Items)
Continue If(*Not #Item.Selected)
#SelectedRows += 1
Endfor
#Selected := #SelectedRows
Endroutine
End_Com
Re: List performance latest EPC
Thank you Stewart. I see how the lost selection is firing 1600 times now.
Art
Art
Art Tostaine
Re: List performance latest EPC
So those 1600 events are still getting fired but with the inclusion of the timer, those events are just starting and stopping the timer, which due to its interval, likely does not fire until the last event when the interval is reached.
I find this technique really interesting and one that I should probably use more of.
I have a lot of cases where I do "automatic lookups" when a control loses focus for advanced users. For example typing in an office or client number instead of looking it up and I need to take the number they typed in and get the name of the entity. The problem with that approach has been it does not fire until the control loses focus and I have to coordinate the Changed and LostFocus events. I think a timer with the changed event may result in a better user experience and reduce the code involved.
Thanks for sharing!
I find this technique really interesting and one that I should probably use more of.
I have a lot of cases where I do "automatic lookups" when a control loses focus for advanced users. For example typing in an office or client number instead of looking it up and I need to take the number they typed in and get the name of the entity. The problem with that approach has been it does not fire until the control loses focus and I have to coordinate the Changed and LostFocus events. I think a timer with the changed event may result in a better user experience and reduce the code involved.
Thanks for sharing!
-
dannyoorburg
- Posts: 177
- Joined: Mon Jan 04, 2016 9:50 am
- Location: Australia
Re: List performance latest EPC
You can see this technique being used in the Visual LANSA IDE as well.
Type in the source editor, wait a split second, and Auto Complete pops up. The magic number for a good user experience seems to be 300 milliseconds.
Cheers,
Danny
Type in the source editor, wait a split second, and Auto Complete pops up. The magic number for a good user experience seems to be 300 milliseconds.
Cheers,
Danny
- Stewart Marshall
- Posts: 417
- Joined: Thu Nov 05, 2015 5:25 pm
Re: List performance latest EPC
Hi Art
A timer ticking on a Changed event will definitely produce a better user experience than using LostFocus.
Have a look at xDemoEditTimer. This part wraps up the timer functionality. For a single control, you can simply invoke the Restart method on every change and then update in the Tick event.
It can also be used for multiple controls on the same page. Set the ActiveControl property whenever a control get Focus. You can use this to determine what processing to call within the Tick.
xDemoEditTimerSample shows it in practice with an edit and a spin edit
Regards
A timer ticking on a Changed event will definitely produce a better user experience than using LostFocus.
Have a look at xDemoEditTimer. This part wraps up the timer functionality. For a single control, you can simply invoke the Restart method on every change and then update in the Tick event.
It can also be used for multiple controls on the same page. Set the ActiveControl property whenever a control get Focus. You can use this to determine what processing to call within the Tick.
xDemoEditTimerSample shows it in practice with an edit and a spin edit
Regards
Re: List performance latest EPC
Sorry for hijacking the topic. That was me (Joe). Just thought that was a great technique that I could use immediately.
Re: List performance latest EPC
Art,
In your original post for this topic, you state you have a list in a VL-WEB app and "we mark them all as selected". How did you set or mark them all as selected? I am trying the same thing (have a list that can be downloaded), but am struggling with or missing the parm or method to "selectAll"?
In your original post for this topic, you state you have a list in a VL-WEB app and "we mark them all as selected". How did you set or mark them all as selected? I am trying the same thing (have a list that can be downloaded), but am struggling with or missing the parm or method to "selectAll"?
Arlyn Dale
Servias LLC
Servias LLC
Re: List performance latest EPC
not at a pc, but after writing the list entry, something like #list1.itemselected := true. You may have to upd_Entry after not sure.
Make sure the list definition allows multiple selections.
Make sure the list definition allows multiple selections.
Art Tostaine
Re: List performance latest EPC
Arlyn,
you can see this in the code from Stewart: (Note: SelectionStyle(All) on the Define_Com)
You can also loop through the items:
you can see this in the code from Stewart: (Note: SelectionStyle(All) on the Define_Com)
Code: Select all
Define_Com Class(#PRIM_LIST) Name(#List) DisplayPosition(2) Left(0) Parent(#COM_OWNER) TabPosition(2) Top(82) Height(463) Width(905) SelectionStyle(All)
Evtroutine Handling(#SelectAll.Click)
* THE NEXT LINE SETS ALL List Items to SELECTED ****
#List.Items<>.Selected := True
#Com_owner.GetSelected
Endroutine
Code: Select all
For Each(#Entry) In(#List)
* You may want to test the entry to determine if you are setting it...
#Entry.Selected := True
EndFor
Re: List performance latest EPC
Art & Brendan,
Excellent. I didn't check in the code from Stewart, but the event routine for "Select All" is exactly what I was looking for.
Thanks.
Excellent. I didn't check in the code from Stewart, but the event routine for "Select All" is exactly what I was looking for.
Thanks.
Arlyn Dale
Servias LLC
Servias LLC