List performance latest EPC

This Q&A forum allows users to post and respond to "How Do I Do ....." questions. Please do not use to report (suspected) errors - you must use your regional help desk for this. The information contained in this forum has not been validated by LANSA and, as such, LANSA cannot guarantee the accuracy of the information.
Post Reply
atostaine
Posts: 696
Joined: Wed Jan 20, 2016 7:38 am

List performance latest EPC

Post by atostaine »

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.
reg.png
reg.png (149.1 KiB) Viewed 25920 times
On the itemgotselection event, we selectlist/endSelect and update our counters. This performs OK.

Thanks for any suggestions, Art
Art Tostaine
User avatar
Stewart Marshall
Posts: 417
Joined: Thu Nov 05, 2015 5:25 pm

Re: List performance latest EPC

Post by Stewart Marshall »

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).

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

Stewart Marshall

Independent IT Consultant
www.marshallfloyd.com.au
atostaine
Posts: 696
Joined: Wed Jan 20, 2016 7:38 am

Re: List performance latest EPC

Post by atostaine »

Thank you Stewart. I see how the lost selection is firing 1600 times now.

Art
Art Tostaine
jyoung
Posts: 694
Joined: Thu Jan 21, 2016 6:43 am
Location: Oklahoma City, OK USA

Re: List performance latest EPC

Post by jyoung »

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!
dannyoorburg
Posts: 177
Joined: Mon Jan 04, 2016 9:50 am
Location: Australia

Re: List performance latest EPC

Post by dannyoorburg »

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
User avatar
Stewart Marshall
Posts: 417
Joined: Thu Nov 05, 2015 5:25 pm

Re: List performance latest EPC

Post by Stewart Marshall »

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
Capture.PNG
Capture.PNG (10.14 KiB) Viewed 25862 times
Regards
Stewart Marshall

Independent IT Consultant
www.marshallfloyd.com.au
jyoung
Posts: 694
Joined: Thu Jan 21, 2016 6:43 am
Location: Oklahoma City, OK USA

Re: List performance latest EPC

Post by jyoung »

Sorry for hijacking the topic. That was me (Joe). Just thought that was a great technique that I could use immediately.
adale
Posts: 212
Joined: Wed Apr 08, 2020 9:18 pm
Location: Poplarville, MS

Re: List performance latest EPC

Post by adale »

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"?
Arlyn Dale
Servias LLC
atostaine
Posts: 696
Joined: Wed Jan 20, 2016 7:38 am

Re: List performance latest EPC

Post by atostaine »

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.
Art Tostaine
BrendanB
Posts: 134
Joined: Tue Nov 24, 2015 10:29 am

Re: List performance latest EPC

Post by BrendanB »

Arlyn,

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
You can also loop through the items:

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
adale
Posts: 212
Joined: Wed Apr 08, 2020 9:18 pm
Location: Poplarville, MS

Re: List performance latest EPC

Post by adale »

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.
Arlyn Dale
Servias LLC
Post Reply