Progress Bar Control Performance Testing

Moderator: Rathinagiri

User avatar
ljubacirovic
Posts: 12
Joined: Thu Mar 27, 2014 6:38 am
DBs Used: DBF, MySQL, MS Access, MS SQL
Been thanked: 1 time

Re: Progress Bar Control Performance Testing

Post by ljubacirovic » Thu Feb 07, 2019 8:53 pm

Hello Marek,

I am certain that your conceptual solution is OK for displaying of indexing flow. I am just wandering if you tested it on a live data and how much processing overhead it produces taking in the account that for every nStep records during indexing it calls Eval -> NtxProgress() -> do events. I am afraid that it may be very time consuming.

Best regards,
Ljuba

User avatar
mol
Posts: 3194
Joined: Thu Sep 11, 2008 5:31 am
Location: Myszków, Poland
Has thanked: 213 times
Been thanked: 120 times
Contact:

Post by mol » Thu Feb 07, 2019 9:13 pm

I had no time to test.
My application reindexes data only in critical situation, so it's not big problem to wait

User avatar
andyglezl
Posts: 1149
Joined: Fri Oct 26, 2012 7:58 pm
Location: Guadalajara Jalisco, MX
Has thanked: 35 times
Been thanked: 68 times
Contact:

Post by andyglezl » Thu Feb 07, 2019 9:34 pm

Quizà de esta manera, simulando la animaciòn de que està trabajando hasta que termine el proceso completo.
*----------------------------------------------------------------------------------------------------------------------------
Maybe in this way, simulating the animation you're working on until the entire process is finished.


http://www.hmgforum.com/viewtopic.php?f ... BAR#p56274
Andrés González López
Desde Guadalajara, Jalisco. México.

User avatar
ljubacirovic
Posts: 12
Joined: Thu Mar 27, 2014 6:38 am
DBs Used: DBF, MySQL, MS Access, MS SQL
Been thanked: 1 time

Post by ljubacirovic » Fri Feb 08, 2019 7:01 am

Hello Andrés,

Yes, your example is OK for the processes where you do not know how long will they take to finish (as the ENABLE MARQUEE is intended for). For example, when application waits response from some source (process, service, server, database, etc.) other than user. But, when you have to conduct some local processing in the previously known number of steps, records or whatsoever value you take as a measurement, then it is very informative to have a counter at least to show the progress. Progress bar is a fancier but more resource consuming way to achieve this. I just tried to point to the overhead/cost of implementing graphical progress control in such a situation. I think that users do not need a nice looking interface which makes them wait 10 times longer than necessary to complete some mundane task. My goal is to balance usability/performance and GUI gadgets.

Ljuba

User avatar
andyglezl
Posts: 1149
Joined: Fri Oct 26, 2012 7:58 pm
Location: Guadalajara Jalisco, MX
Has thanked: 35 times
Been thanked: 68 times
Contact:

Post by andyglezl » Fri Feb 08, 2019 3:42 pm

Claro que se puede modificar y adaptar a diferentes necesidades,
por ejemplo:

En vez de utilizar ENABLE MARQUEE, se puede crear un LABEL donde
se esté desplegando el valor correspondiente al contador que quieras llevar.
+----------------------------------------------------------------------------------------------
Of course, it can be modified and adapted to different needs,
for example:

Instead of using ENABLE MARQUEE, you can create a LABEL where
the value corresponding to the counter you want to carry is being displayed.
Andrés González López
Desde Guadalajara, Jalisco. México.

User avatar
ljubacirovic
Posts: 12
Joined: Thu Mar 27, 2014 6:38 am
DBs Used: DBF, MySQL, MS Access, MS SQL
Been thanked: 1 time

Post by ljubacirovic » Fri Feb 08, 2019 8:08 pm

Hello Andrés,

Obviously you have not noticed the code within my original post that I used to compare performances of progress bar versus label. Anyway, I appreciate your interest for the topic.

Ljuba

User avatar
andyglezl
Posts: 1149
Joined: Fri Oct 26, 2012 7:58 pm
Location: Guadalajara Jalisco, MX
Has thanked: 35 times
Been thanked: 68 times
Contact:

Post by andyglezl » Sat Feb 09, 2019 2:14 am

Pongo a su consideración lo siguiente...
*-------------------------------------------------------
I put to your consideration the following ...

Code: Select all

	
    #include 'hmg.ch'
	
	PROCEDURE ProgTest
	/*
    
    */
        PRIVATE cProgCh
        
        SET CODEPAGE TO ENGLISH
        cProgCh := chr(254)
        
        DEFINE WINDOW wProgTest ;
            AT 10, 10 ;
            WIDTH 420 HEIGHT 250 ;
            TITLE "Progress Indicator Testing" ;
            ICON NIL CHILD CURSOR NIL ;
            ON INTERACTIVECLOSE NIL ;
            ON GOTFOCUS NIL ;
            ON LOSTFOCUS NIL

            DEFINE LABEL lbSteps
                PARENT wProgTest
                ROW 20 
                COL 10
                VALUE "Enter number of steps for the test loop"
                WIDTH 220
                HEIGHT 20
            END LABEL

            DEFINE TEXTBOX tbSteps
                PARENT wProgTest
                ROW 18
                COL 250
                HEIGHT 20
                VALUE 10000
                WIDTH 100
                INPUTMASK '999,999,999'
                FORMAT 'E'
                MAXLENGTH 9
                DATATYPE NUMERIC
                MAXLENGTH 9
                ONGOTFOCUS wProgTest.tbSteps.CaretPos := 8
                ONENTER wProgTest.btExecute.SetFocus
                RIGHTALIGN .T.
                VISIBLE .T.
                TABSTOP .T.
            END TEXTBOX
 
            DEFINE CHECKBOX cbProgBar
                PARENT wProgTest
                ROW 80
                COL 10
                CAPTION 'Progress bar'
                VALUE .F.
                WIDTH 100
                HEIGHT 20
                TOOLTIP 'Check if you want to test progress bar as progress indicator.'
                VISIBLE .T.
                TABSTOP .T.
            END CHECKBOX
             
            DEFINE PROGRESSBAR pbFlow
                ROW    80
                COL    110
                WIDTH  270
                HEIGHT 20
                RANGEMIN 1
                RANGEMAX 100
                VALUE 1
                TOOLTIP ""
                HELPID Nil
                VISIBLE .f.
                VERTICAL .F. 
            END PROGRESSBAR  

            DEFINE CHECKBOX cbLablBar
                PARENT wProgTest
                ROW 100
                COL 10
                CAPTION 'Label bar'
                VALUE .F.
                WIDTH 100
                HEIGHT 20
                TOOLTIP 'Check if you want to test label as progress indicator.'
                VISIBLE .T.
                TABSTOP .T.
            END CHECKBOX

            DEFINE LABEL lbFlow
                PARENT wProgTest
                ROW 100 
                COL 110
                VALUE ""
                WIDTH 10
                HEIGHT 50
                FONTCOLOR {0,76,153}
            END LABEL

            DEFINE BUTTON btExecute
                ROW    180
                COL    110
                WIDTH  200
                HEIGHT 25
                ACTION {TestInd(), wProgTest.tbSteps.SetFocus}
                CAPTION "Execute"
                TOOLTIP "Accept entered parameters and execute test."
                TABSTOP .T.
                VISIBLE .T.
            END BUTTON 
 
        END WINDOW	
        
        wProgTest.tbSteps.SetFocus
        wProgTest.Center
        wProgTest.Activate
    
    RETURN NIL	

//*---->

	FUNCTION TestInd
	/*
    
    */   

        nKfLb := 0
        nSteps := wProgTest.tbSteps.Value
        nStart:= SECONDS()
        IF wProgTest.cbProgBar.Value
            cTest := wProgTest.cbProgBar.Caption+' as progress indicator'
            wProgTest.pbFlow.RangeMax := nSteps
            wProgTest.pbFlow.Visible := wProgTest.cbProgBar.Value
        ELSEIF wProgTest.cbLablBar.Value
            cTest := wProgTest.cbLablBar.Caption+' as progress indicator'
            wProgTest.lbFlow.Visible := wProgTest.cbLablBar.Value
            wProgTest.lbFlow.Width := wProgTest.Width-wProgTest.lbFlow.Col
            nKfLb := (wProgTest.lbFlow.Width/wProgtest.lbFlow.FontSize)/105 
        ELSE
            cTest := 'Without progress indicator'
        END       

		
wProgTest.pbFlow.RangeMax := nSteps	//*************************** ADD THIS
*wProgTest.pbFlow.RangeMax := ALIAS->(lastrec())	//	Define the number of total steps        

        FOR nI := 1 TO nSteps     
			IF RIGHT( STR(nI,6), 1) = "0"		//*************************** ADD THIS		//	show every 10 steps
				IF wProgTest.cbProgBar.Value               
					IF nI==wProgTest.pbFlow.RangeMax    
	*                    wProgTest.pbFlow.RangeMax := wProgTest.pbFlow.RangeMax + 1		//*************************** COMMENT THIS
						wProgTest.pbFlow.Value := nI // + 1								//*************************** COMMENT THIS
	*                    wProgTest.pbFlow.RangeMax := wProgTest.pbFlow.RangeMax - 1		//*************************** COMMENT THIS
					ELSE
						wProgTest.pbFlow.Value := nI + 1   
					ENDIF
					wProgTest.pbFlow.Value := nI
				ELSEIF wProgTest.cbLablBar.Value
					nRatio := INT((nI/nSteps)*100)
					wProgTest.lbFlow.Value := REPLICATE(cProgCh,INT(nRatio*nKfLb))+' '+LTRIM(STR(nRatio))+'%'                
				END
			ENDIF					//*************************** ADD THIS


			/*
				***************  Más el tiempo que se tarde en hacer cualquier proceso...
				***************  Plus the time it takes to do any process...
				***************	 Append, Replace, Delete, etc., etc.
			*/
            DO EVENTS
        NEXT             
        MsgInfo(cTest+' -> '+LTRIM(STR(SECONDS() - nStart))+ " seconds",'TEST DURATION')
        
        wProgTest.pbFlow.Visible := wProgTest.cbProgBar.Value := .F.
        wProgTest.lbFlow.Visible := wProgTest.cbLablBar.Value := .F.
        wProgTest.btExecute.Caption := "Execute"
        
    RETURN NIL

//*---->
Andrés González López
Desde Guadalajara, Jalisco. México.

User avatar
ljubacirovic
Posts: 12
Joined: Thu Mar 27, 2014 6:38 am
DBs Used: DBF, MySQL, MS Access, MS SQL
Been thanked: 1 time

Post by ljubacirovic » Sat Feb 09, 2019 5:42 pm

Hello Andrés,

Thank you on your suggestions, I reviewed and tested them.
What I liked is the idea to shorten the IF statement within the loop. At first, I thought it would cause problems in displaying progress bar control under Aero theme. But at my utter joy it worked. So I changed the condition to < instead of == and removed FOUR lines of code. It did not speed up the process but the code is simpler/shorter now.
Also, I introduced nQt := 100/nSteps and put it before loop so there is one calculation less per step.
====> UPDATE !!!
After more thorough testing of this shortened IF construct I realized that it does not perform as expected. That is, progress bar fills up AFTER the message of the process completion is displayed. Therefore, I discarded the shortened IF construct and reversed to the original one. Only then progress bar fills up BEFORE the message of the process completion is displayed. Unfortunately, my first hunch was correct.
<==== UPDATE !!!
I would like to remind you of the value limitation for RangeMax which is set to two bytes in HMG (max 65,535) although Windows documentation says that Windows progress bar accepts 32 bit value for RangeMax. I suppose that some C modul of HMG needs to be modified and recompiled. Therefore, I would not recommend you to set RangeMax to nSteps when nSteps maximum input value is set to 999,999,999!
Now, the purpose of this test is to compare execution speeds, step by step, under the same conditions, for two different ways of displaying progress. Introducing technique to skip 10 steps is not in line with the purpose of the test, because it would yield some dubious performance results. Also, there is a simpler way to check if the number ends with "0" using the modulus operator IF nX%10 == 0. I believe that you overlooked it in your eagerness.
Here is the modified code.

Code: Select all


	FUNCTION TestInd
	/*
    
    	*/   
        nKfLb := 0
        nSteps := wProgTest.tbSteps.Value
        nStart:= SECONDS()

        IF wProgTest.cbProgBar.Value
            cTest := wProgTest.cbProgBar.Caption+' as progress indicator'
            wProgTest.pbFlow.RangeMax := 100
            wProgTest.pbFlow.Visible := wProgTest.cbProgBar.Value
        ELSEIF wProgTest.cbLablBar.Value
            cTest := wProgTest.cbLablBar.Caption+' as progress indicator'
            wProgTest.lbFlow.Visible := wProgTest.cbLablBar.Value
            wProgTest.lbFlow.Width := wProgTest.Width-wProgTest.lbFlow.Col
            nKfLb := (wProgTest.lbFlow.Width/wProgtest.lbFlow.FontSize)/105 
        ELSE
            cTest := 'Without progress indicator'
        END               
        nQt := 100/nSteps	//<== This a new variable, quotient for percentage recalculation.
        nI := 0
        while ++nI<=nSteps	//<== DO WHILE ... END DO loop instead of FOR ... NEXT loop
            nRatio := INT(nI*nQt)	//	<== Simplified calculation within loop
            IF wProgTest.cbProgBar.Value
                /*
                IF nRatio<wProgTest.pbFlow.RangeMax 	//	<== Modified condition and simplified IF ... ENDIF block. ==>DISCARDED
                    wProgTest.pbFlow.Value := nRatio + 1   
                ENDIF
                */
                IF nRatio==wProgTest.pbFlow.RangeMax      //	<== 	Original IF ... ENDIF block, ensures that progress bar is filled up BEFORE the message
                								//		of the process completion is displayed.    
                    wProgTest.pbFlow.RangeMax := wProgTest.pbFlow.RangeMax + 1      
                    wProgTest.pbFlow.Value := nRatio + 1
                    wProgTest.pbFlow.RangeMax := wProgTest.pbFlow.RangeMax - 1                 
                ELSE
                    wProgTest.pbFlow.Value := nRatio + 1   
                ENDIF  
                wProgTest.pbFlow.Value := nRatio
            ELSEIF wProgTest.cbLablBar.Value               
                wProgTest.lbFlow.Value := REPLICATE(cProgCh,INT(nRatio*nKfLb))+' '+LTRIM(STR(nRatio))+'%'                
            END
            wProgTest.btExecute.Caption := 'Step '+LTRIM(STR(nI))+' of '+LTRIM(STR(nSteps))
            DO EVENTS
        end
        MsgInfo(cTest+' -> '+LTRIM(STR(SECONDS() - nStart))+ " seconds",'TEST DURATION')
        
        wProgTest.pbFlow.Visible := wProgTest.cbProgBar.Value := .F.
        wProgTest.lbFlow.Visible := wProgTest.cbLablBar.Value := .F.
        wProgTest.btExecute.Caption := "Execute"

    RETURN NIL

Post Reply