Announcement

Collapse
1 of 2 < >

New Sub-Forum

In an effort to help make sure there are appropriate categories for topics of discussion that are happening, there is now a sub-forum for databases and database programming under Special Interest groups. Please direct questions, etc., about this topic to that sub-forum moving forward. Thank you.
2 of 2 < >

Forum Guidelines

This forum is for finished source code that is working properly. If you have questions about this or any other source code, please post it in one of the Discussion Forums, not here.
See more
See less

PB Benchmark

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

  • PBWin PB Benchmark

    This was in response to a query by Tim Collins here.
    Comments here.
    Code:
    #COMPILE EXE "Benchmark.exe"
    #DIM ALL
    
    'designed for PBWIN 10.4 and J Roca includes
    'by: Jim Fritts
    'Stable benchmarking platform to compare the completion time for 2 different routines using 100 iterations for each process.
    'Stability is +/- 0.001 seconds.
    'All string assignments should be done outside the thread to promote stability.
    
    #INCLUDE "win32api.inc"
    
    GLOBAL gAction  AS LONG
    GLOBAL g_Result AS LONG
    GLOBAL gsX      AS STRING
    GLOBAL gsY      AS STRING
    GLOBAL gsZ      AS STRING
    GLOBAL XC       AS LONG
    GLOBAL DONE     AS DOUBLE
    GLOBAL TEST1    AS DOUBLE
    GLOBAL TEST2    AS DOUBLE
    GLOBAL START    AS DOUBLE
    
    
    FUNCTION PBMAIN AS LONG
    
      gsX = STRING$(80, "X")   'create the test string
      gsY = STRING$(80, "Y")   'create the test string
      gsZ = STRING$(80, "Z")   'create the test string
      SLEEP 2
    
      LOCAL hThread AS DWORD
      THREAD CREATE ProcessTest(1) TO hThread  'run real-time comparison thread
      THREAD CLOSE hThread TO hThread
      SLEEP 10
    
      DO WHILE gAction = 1
          SLEEP 10
      LOOP
    END FUNCTION
    
    THREAD FUNCTION ProcessTest(BYVAL yyy AS LONG) AS LONG
        gAction = 1
    
        g_Result = SetPriorityClass(GetCurrentProcess(), %REALTIME_PRIORITY_CLASS)
    
        'Compare the times for processing each routine
        Start = TIMER
    
        FOR XC = 1 TO 100
            GOSUB Process_1
            SLEEP 1
        NEXT
    
        Done = TIMER
        Test1 = Done - Start
    
        Start = TIMER
    
        FOR XC = 1 TO 100
            GOSUB Process_2
            SLEEP 1
        NEXT
    
        Done = TIMER
        Test2 = Done - Start
    
        ? "Process Completed." + $CRLF + _
            USING$("&##.####", "Seconds using three strings", Test1) + $CRLF + _
            USING$("&##.####", "Seconds using concatenation", Test2)
        gAction = 0
    
        g_Result = SetPriorityClass(GetCurrentProcess(), %NORMAL_PRIORITY_CLASS)
        EXIT FUNCTION
    
        Process_1:
            'Put your code here
            'PRINT gsX; gsY; gsZ
        RETURN
    
        Process_2:
            'Put your code here
            'PRINT BUILD$(gsX, gsY, gsZ)
        RETURN
    
    END FUNCTION
    Last edited by Jim Fritts; 23 Jul 2019, 12:03 PM.

  • #2
    Here is another attempt. It even tells you if the
    time difference in the routines is significant. Enjoy

    NOTE:
    You may need to change the variance for your
    system. Currently it is fixed at 0.0000320
    and the iterations are fixed at 1000.
    If you do chose to run 10,000 iterations
    then your variance should be 0.0000375.

    Code:
    #COMPILE EXE "PB_Benchmark_2.exe"
    #DIM ALL
    
    'designed for PBWIN 10.4 and J Roca includes
    'by: Jim Fritts on 26 JUL 2019
    'Compare the completion time for 2 different routines using 1000 iterations for each process.
    'Parallel processing method which forces routines to share cycles rather than run routines end to end as in the previous method.
    'All string assignments should be done outside the threads to promote stability.
    'Much improved over the previous method.
    
    #INCLUDE "win32api.inc"
    
    GLOBAL gAction1  AS LONG
    GLOBAL gAction2  AS LONG
    GLOBAL g_Result  AS LONG
    GLOBAL gsX       AS STRING
    GLOBAL gsY       AS STRING
    GLOBAL gsZ       AS STRING
    GLOBAL Test1     AS DOUBLE
    GLOBAL Test2     AS DOUBLE
    GLOBAL giIterate AS LONG
    GLOBAL giSync    AS LONG
    
    
    FUNCTION PBMAIN AS LONG
        LOCAL lsOutput AS STRING
    
        gsX = STRING$(80, "X")   'create the test string
        gsY = STRING$(80, "Y")   'create the test string
        gsZ = STRING$(80, "Z")   'create the test string
        giIterate = 1000
    
        SLEEP 2
    
        LOCAL hThread1 AS DWORD
        THREAD CREATE ProcessTest1(1) TO hThread1
        THREAD CLOSE hThread1 TO hThread1
    
        LOCAL hThread2 AS DWORD
        THREAD CREATE ProcessTest2(1) TO hThread2
        THREAD CLOSE hThread2 TO hThread2
        SLEEP 10
    
        giSync = 1
    
        DO WHILE gAction1 = 1 OR gAction2 = 1
            SLEEP 10
        LOOP
        lsOutput = "Process Completed." + $CRLF + _
            USING$("&##.#######", "Test 1 average time per loop at " + STR$(giIterate) + " iterations = ", Test1) + $CRLF + _
            USING$("&##.#######", "Test 2 average time per loop at " + STR$(giIterate) + " iterations = ", Test2) + $CRLF + $CRLF + _
            USING$("&##.#######", "The variance is ", ABS(Test1 - Test2)) + $CRLF
        IF ABS(Test1 - Test2) <= 0.0000320 THEN
            lsOutput = lsOutput + "Not significant."
        ELSE
            lsOutput = lsOutput + "Is significant."
        END IF
        ? lsOutput
    END FUNCTION
    
    THREAD FUNCTION ProcessTest1(BYVAL yyy AS LONG) AS LONG
        LOCAL XC    AS LONG
        LOCAL XA    AS LONG
        LOCAL gsA   AS STRING
        LOCAL Done  AS DOUBLE
        LOCAL Start AS DOUBLE
    
        gAction1 = 1
    
        CheckAgain:
        IF giSync = 1 THEN
            gsA = ""
    
            GOSUB DoProcess
    
            gAction1 = 0
            EXIT FUNCTION
        END IF
        GOTO CheckAgain
        EXIT FUNCTION
    
        DoProcess:
            g_Result = SetPriorityClass(GetCurrentProcess(), %REALTIME_PRIORITY_CLASS)
    
            FOR XC = 1 TO 1
                Start = TIMER
                FOR XA = 1 TO giIterate
                   'Put your code here
                    gsA = gsA + gsX + gsY + gsZ + $CRLF
                NEXT
                Done = TIMER
                Test1 = (Done - Start)/giIterate
    
            NEXT
        RETURN
    
    END FUNCTION
    
    THREAD FUNCTION ProcessTest2(BYVAL yyy AS LONG) AS LONG
        LOCAL XC    AS LONG
        LOCAL XA    AS LONG
        LOCAL gsA   AS STRING
        LOCAL Done  AS DOUBLE
        LOCAL Start AS DOUBLE
    
        gAction2 = 1
    
        CheckAgain:
        IF giSync = 1 THEN
            gsA = ""
    
            GOSUB DoProcess
    
            gAction2 = 0
            EXIT FUNCTION
        END IF
        GOTO CheckAgain
        EXIT FUNCTION
    
        DoProcess:
            g_Result = SetPriorityClass(GetCurrentProcess(), %REALTIME_PRIORITY_CLASS)
    
            FOR XC = 1 TO 1
    
                Start = TIMER
                FOR XA = 1 TO giIterate
                   'Put your code here
                    gsA = gsA + gsX + gsY + gsZ + $CRLF
                    'gsA = build$(gsA, gsX, gsY, gsZ, $CRLF)
                NEXT
                Done = TIMER
                Test2 = (Done - Start)/giIterate
    
            NEXT
        RETURN
    
    END FUNCTION
    If you do chose to run 10,000 iterations then your variance should be 0.0000375.
    Last edited by Jim Fritts; 26 Jul 2019, 04:57 PM.

    Comment


    • #3
      Version 3 with integrated variance calculator.
      Code:
      #COMPILE EXE "PB_Benchmark_3.exe"
      #DIM ALL
      
      'designed for PBWIN 10.4 and J Roca includes
      'by: Jim Fritts on 26 JUL 2019
      'Development platform is:
      'Windows 10 version 1809.
      '9 year old Toshiba Satellite Laptop.
      'Object:
      'Compare the completion time for 2 different routines using 1000 iterations for each process.
      'Method:
      'Parallel processing which forces routines to share cycles rather than run routines end to end.
      'All string assignments should be done outside the threads to promote stability.
      'Slightly improved over the previous method. Now with an integrated variance calculator.
      'NOTE:
      'You may need to change the variance for your system.
      'The currently acceptable variance for 1000 iterations is fixed at 0.0000320.
      'When testing above 3000 iterations you may get corrupted results while the OS is overtaxed.
      'Likely you'll want to avoid doing that.
      'If your iterations go below 351 you will not be allowed to continue because the sample is too small to adequately measure.
      
      #INCLUDE "win32api.inc"
      
      GLOBAL gAction1  AS LONG
      GLOBAL gAction2  AS LONG
      GLOBAL g_Result  AS LONG
      GLOBAL gsX       AS STRING
      GLOBAL gsY       AS STRING
      GLOBAL gsZ       AS STRING
      GLOBAL Test1     AS DOUBLE
      GLOBAL Test2     AS DOUBLE
      GLOBAL giIterate AS LONG
      GLOBAL giSync    AS LONG
      GLOBAL Variance  AS DOUBLE
      GLOBAL DeltaV    AS DOUBLE
      
      FUNCTION PBMAIN AS LONG
          LOCAL lsOutput AS STRING
      
          gsX = STRING$(80, "X")   'create the test string
          gsY = STRING$(80, "Y")   'create the test string
          gsZ = STRING$(80, "Z")   'create the test string
          giIterate = 1000         '<-- select your test iterations here (1000 is very speedy and fairly accurate)
      
          'Calculating the variance that is accepable
          IF giIterate >= 1000 THEN
              DeltaV = giIterate - 1000
              Variance = 0.0000320 + DeltaV * 6.1111 * EXP10(-10)
          ELSE
              Variance = 0.0000320
          END IF
      
          SLEEP 2
      
          IF giIterate <= 350 THEN
              ? "Sorry, the requested tests could not be run. giIterate is too low for an adequate sample."
              GOTO CloseDown
          END IF
      
          LOCAL hThread1 AS DWORD
          THREAD CREATE ProcessTest1(1) TO hThread1
          THREAD CLOSE hThread1 TO hThread1
      
          LOCAL hThread2 AS DWORD
          THREAD CREATE ProcessTest2(1) TO hThread2
          THREAD CLOSE hThread2 TO hThread2
      
          SLEEP 10
      
          giSync = 1
      
          DO WHILE gAction1 = 1 OR gAction2 = 1
              SLEEP 10
          LOOP
          lsOutput = "Process Completed." + $CRLF + _
              USING$("&##.#######", "Test 1 average time per loop at " + STR$(giIterate) + " iterations = ", Test1) + $CRLF + _
              USING$("&##.#######", "Test 2 average time per loop at " + STR$(giIterate) + " iterations = ", Test2) + $CRLF + $CRLF + _
              USING$("&##.#######", "The variance is ", ABS(Test1 - Test2)) + $CRLF
          IF ABS(Test1 - Test2) <= Variance THEN
              lsOutput = lsOutput + "Not significant."
          ELSE
              lsOutput = lsOutput + "Is significant."
          END IF
          ? lsOutput
      
          CloseDown:
      END FUNCTION
      
      THREAD FUNCTION ProcessTest1(BYVAL yyy AS LONG) AS LONG
          LOCAL XC    AS LONG
          LOCAL XA    AS LONG
          LOCAL gsA   AS STRING
          LOCAL Done  AS DOUBLE
          LOCAL Start AS DOUBLE
      
          gAction1 = 1
      
          CheckAgain:
          IF giSync = 1 THEN
              gsA = ""
      
              GOSUB DoProcess
      
              gAction1 = 0
              EXIT FUNCTION
          END IF
          GOTO CheckAgain
          EXIT FUNCTION
      
          DoProcess:
              g_Result = SetPriorityClass(GetCurrentProcess(), %REALTIME_PRIORITY_CLASS)
      
              FOR XC = 1 TO 1
                  Start = TIMER
                  FOR XA = 1 TO giIterate
                     'Put your code here
                      gsA = gsA + gsX + gsY + gsZ + $CRLF
                  NEXT
                  Done = TIMER
                  Test1 = (Done - Start)/giIterate
      
              NEXT
          RETURN
      
      END FUNCTION
      
      THREAD FUNCTION ProcessTest2(BYVAL yyy AS LONG) AS LONG
          LOCAL XC    AS LONG
          LOCAL XA    AS LONG
          LOCAL gsA   AS STRING
          LOCAL Done  AS DOUBLE
          LOCAL Start AS DOUBLE
      
          gAction2 = 1
      
          CheckAgain:
          IF giSync = 1 THEN
              gsA = ""
      
              GOSUB DoProcess
      
              gAction2 = 0
              EXIT FUNCTION
          END IF
          GOTO CheckAgain
          EXIT FUNCTION
      
          DoProcess:
              g_Result = SetPriorityClass(GetCurrentProcess(), %REALTIME_PRIORITY_CLASS)
      
              FOR XC = 1 TO 1
      
                  Start = TIMER
                  FOR XA = 1 TO giIterate
                     'Put your code here
                      gsA = gsA + gsX + gsY + gsZ + $CRLF
                      'gsA = build$(gsA, gsX, gsY, gsZ, $CRLF)
                  NEXT
                  Done = TIMER
                  Test2 = (Done - Start)/giIterate
      
              NEXT
          RETURN
      
      END FUNCTION

      Comment


      • #4
        PB_Benchmark version 4
        Yes, you can get different results every time you run this. Not a problem. Consider the Beast of Windows and take the average of your results;
        however, comparatively speaking the 3rd run does look to be the most accurate of the runs. I will have to consider that in any further development.
        We shall see.

        Click image for larger version  Name:	PB_Benchmark.jpg Views:	0 Size:	45.6 KB ID:	783193

        Code:
        #COMPILE EXE "PB_Benchmark_4.exe"
        #DIM ALL
        
        'designed for PBWIN 10.4 and J Roca includes
        'Released by: Jim Fritts on 28 JUL 2019
        'Development platform is:
        'Windows 10 version 1809.
        '9 year old Toshiba Satellite Laptop.
        'Object:
        'Compare the completion time for 2 different routines using 1000 iterations for each process.
        'Version 4 runs the routines 3 times and presents a final comparitive report for all 3 runs.
        'Method:
        'Parallel processing which forces routines to share cycles rather than run routines end to end.
        'All string assignments should be done outside the threads to promote stability.
        'Slightly improved over the previous method. Now with an integrated variance calculator.
        'NOTE:
        'You may need to change the variance for your system.
        'The currently acceptable variance for 1000 iterations is fixed at 0.0000320.
        'When testing above 3000 iterations you may get corrupted results while the OS is overtaxed.
        'Likely you'll want to avoid doing that.
        'If your iterations go below 1000 you will not be allowed to continue because the sample is too small to adequately measure.
        
        #INCLUDE "win32api.inc"
        
        GLOBAL gAction1    AS LONG
        GLOBAL gAction2    AS LONG
        GLOBAL g_Result    AS LONG
        GLOBAL gsX         AS STRING
        GLOBAL gsY         AS STRING
        GLOBAL gsZ         AS STRING
        GLOBAL Test1       AS DOUBLE
        GLOBAL Test2       AS DOUBLE
        GLOBAL giSync      AS LONG
        GLOBAL giIterate   AS LONG
        
        FUNCTION PBMAIN AS LONG
            LOCAL lsOutput        AS STRING
            LOCAL XC              AS LONG
            LOCAL Variance        AS DOUBLE
            LOCAL DeltaV          AS DOUBLE
            LOCAL Avg()           AS DOUBLE
            LOCAL AvgTotalTest_1  AS DOUBLE
            LOCAL AvgTotalTest_2  AS DOUBLE
            LOCAL FinalDet        AS DOUBLE
            LOCAL NotifyValue     AS LONG
        
            DIM AVG(1 TO 3, 1 TO 3)
        
            gsX = STRING$(80, "X")   'create the test string
            gsY = STRING$(80, "Y")   'create the test string
            gsZ = STRING$(80, "Z")   'create the test string
            giIterate = 1000         '<-- select your test iterations here (1000 is very speedy and fairly accurate)
        
            'Calculating the variance that is accepable
            IF giIterate >= 1000 THEN
                DeltaV = giIterate - 1000
                Variance = 0.0000320 + DeltaV * 6.1111 * EXP10(-10)
            ELSE
                Variance = 0.0000320
            END IF
        
            SLEEP 2
        
            IF giIterate < 1000 THEN
                ? "Sorry, the requested tests could not be run. giIterate is too low for an adequate sample."
                GOTO CloseDown
            END IF
        
            FOR XC = 1 TO 3  'do 3 runs
        
                LOCAL hThread1 AS DWORD
                THREAD CREATE ProcessTest1(1) TO hThread1
                THREAD CLOSE hThread1 TO hThread1
        
                LOCAL hThread2 AS DWORD
                THREAD CREATE ProcessTest2(1) TO hThread2
                THREAD CLOSE hThread2 TO hThread2
        
                SLEEP 10
        
                giSync = 1
        
                DO WHILE gAction1 = 1 OR gAction2 = 1
                    SLEEP 10
                LOOP
                g_Result = SetPriorityClass(GetCurrentProcess(), %NORMAL_PRIORITY_CLASS)
                AVG(XC, 1) = Test1
                AVG(XC, 2) = Test2
                AVG(XC, 3) = ABS(Test1 - Test2)
        
            NEXT
        
            lsOutput = _
                "Run 1 Completed." + $CRLF + _
                USING$("&##.#######", "Test 1 average time per loop at " + STR$(giIterate) + " iterations = ", AVG(1, 1)) + $CRLF + _
                USING$("&##.#######", "Test 2 average time per loop at " + STR$(giIterate) + " iterations = ", AVG(1, 2)) + $CRLF + $CRLF + _
                USING$("&##.#######", "The variance is ", AVG(1, 3)) + $CRLF
            IF AVG(1, 3) <= Variance THEN
                lsOutput = lsOutput + "Not significant."
            ELSE
                lsOutput = lsOutput + "Is significant."
            END IF
        
            lsOutput = lsOutput + $CRLF + $CRLF + _
                "Run 2 Completed." + $CRLF + _
                USING$("&##.#######", "Test 1 average time per loop at " + STR$(giIterate) + " iterations = ", AVG(2, 1)) + $CRLF + _
                USING$("&##.#######", "Test 2 average time per loop at " + STR$(giIterate) + " iterations = ", AVG(2, 2)) + $CRLF + $CRLF + _
                USING$("&##.#######", "The variance is ", AVG(2, 3)) + $CRLF
            IF AVG(2, 3) <= Variance THEN
                lsOutput = lsOutput + "Not significant."
            ELSE
                lsOutput = lsOutput + "Is significant."
            END IF
        
            lsOutput = lsOutput + $CRLF + $CRLF + _
                "Run 3 Completed." + $CRLF + _
                USING$("&##.#######", "Test 1 average time per loop at " + STR$(giIterate) + " iterations = ", AVG(3, 1)) + $CRLF + _
                USING$("&##.#######", "Test 2 average time per loop at " + STR$(giIterate) + " iterations = ", AVG(3, 2)) + $CRLF + $CRLF + _
                USING$("&##.#######", "The variance is ", AVG(3, 3)) + $CRLF
            IF AVG(3, 3) <= Variance THEN
                lsOutput = lsOutput + "Not significant."
            ELSE
                lsOutput = lsOutput + "Is significant."
            END IF
        
            'do total averaging here
            AvgTotalTest_1 = (AVG(1,1) + AVG(2,1) + AVG(3,1))/3
            AvgTotalTest_2 = (AVG(1,2) + AVG(2,2) + AVG(3,2))/3
        
            lsOutput = lsOutput + $CRLF + $CRLF + _
                USING$("&##.#######", "Test 1 average loop time = ", AvgTotalTest_1) + $CRLF + _
                USING$("&##.#######", "Test 2 average loop time = ", AvgTotalTest_2) + $CRLF
        
            IF AvgTotalTest_1 = AvgTotalTest_2 THEN
                NotifyValue = 0
                FinalDet = 0
            END IF
            IF AvgTotalTest_1 > AvgTotalTest_2 THEN
                NotifyValue = 1
                FinalDet = AvgTotalTest_1/AvgTotalTest_2
            END IF
            IF AvgTotalTest_1 < AvgTotalTest_2 THEN
                NotifyValue = 2
                FinalDet = AvgTotalTest_2/AvgTotalTest_1
            END IF
        
            SELECT CASE NotifyValue
                CASE 0
                    lsOutput = lsOutput + $CRLF + $CRLF + _
                    "The tests did not show any difference in the code segments."
                CASE 1
                    IF ABS(AvgTotalTest_1 - AvgTotalTest_2) <= Variance THEN
                        lsOutput = lsOutput + $CRLF + $CRLF + _
                        "The tests did not show any difference in the code segments."
                    ELSE
                        lsOutput = lsOutput + $CRLF + $CRLF + _
                        USING$("&##.#######", "Code segment 2 is ", FinalDet) + " times faster than code segment 1."
                    END IF
                CASE 2
                    IF ABS(AvgTotalTest_1 - AvgTotalTest_2) <= Variance THEN
                        lsOutput = lsOutput + $CRLF + $CRLF + _
                        "The tests did not show any difference in the code segments."
                    ELSE
                        lsOutput = lsOutput + $CRLF + $CRLF + _
                        USING$("&##.#######", "Code segment 1 is ", FinalDet) + " times faster than code segment 2."
                    END IF
        
            END SELECT
        
            ? lsOutput
            CloseDown:
        END FUNCTION
        
        THREAD FUNCTION ProcessTest1(BYVAL yyy AS LONG) AS LONG
            LOCAL XA    AS LONG
            LOCAL gsA   AS STRING
            LOCAL Done  AS DOUBLE
            LOCAL Start AS DOUBLE
        
            gAction1 = 1
        
            CheckAgain:
            IF giSync = 1 THEN
                gsA = ""
        
                GOSUB DoProcess
        
                gAction1 = 0
                EXIT FUNCTION
            END IF
            GOTO CheckAgain
            EXIT FUNCTION
        
            DoProcess:
                g_Result = SetPriorityClass(GetCurrentProcess(), %REALTIME_PRIORITY_CLASS)
        
                Start = TIMER
                FOR XA = 1 TO giIterate
                   'Put your code here
                    gsA = gsA + gsX + gsY + gsZ + $CRLF
                NEXT
                Done = TIMER
                Test1 = (Done - Start)/giIterate
        
            RETURN
        
        END FUNCTION
        
        THREAD FUNCTION ProcessTest2(BYVAL yyy AS LONG) AS LONG
            LOCAL XA    AS LONG
            LOCAL gsA   AS STRING
            LOCAL Done  AS DOUBLE
            LOCAL Start AS DOUBLE
        
            gAction2 = 1
        
            CheckAgain:
            IF giSync = 1 THEN
                gsA = ""
        
                GOSUB DoProcess
        
                gAction2 = 0
                EXIT FUNCTION
            END IF
            GOTO CheckAgain
            EXIT FUNCTION
        
            DoProcess:
                g_Result = SetPriorityClass(GetCurrentProcess(), %REALTIME_PRIORITY_CLASS)
        
                Start = TIMER
                FOR XA = 1 TO giIterate
                   'Put your code here
                    'gsA = gsA + gsX + gsY + gsZ + $CRLF
                    gsA = BUILD$(gsA, gsX, gsY, gsZ, $CRLF)
                    'NOTE: With BUILD$ "Generally speaking, the greater the number of parameters,
                    'the greater the increase in execution speed." Bob Zale
                    'Build or concatenate strings with very high efficiency.
        
                NEXT
                Done = TIMER
                Test2 = (Done - Start)/giIterate
        
            RETURN
        
        END FUNCTION

        Comment


        • #5
          PB_Benchmark Version 5.
          For better accuracy I use 10,000 iterations of Test1 and 10,000 iterations of Test2 and only using the lowest values of each to calculate the difference between them.
          Click image for larger version

Name:	PB_Benchmark.jpg
Views:	334
Size:	17.0 KB
ID:	783212
          Code:
          #COMPILE EXE "PB_Benchmark_5.exe"
          #DIM ALL
          
          'designed for PBWIN 10.4 and J Roca includes
          'Released by: Jim Fritts on 28 JUL 2019
          'Development platform is:
          'Windows 10 version 1809.
          '9 year old Toshiba Satellite Laptop.
          'Object:
          'Compare the completion time for 2 different routines using 1000 iterations for each process.
          'Version 4 runs the routines 3 times and presents a final comparitive report for all 3 runs.
          'Method:
          'Parallel processing which forces routines to share cycles rather than run routines end to end.
          'All string assignments should be done outside the threads to promote stability.
          'Slightly improved over the previous method. Now with an integrated variance calculator.
          'NOTE:
          'You may need to change the variance for your system.
          'The currently acceptable variance for 1000 iterations is fixed at 0.0000320.
          'When testing above 3000 iterations you may get corrupted results while the OS is overtaxed.
          'Likely you'll want to avoid doing that.
          'If your iterations go below 1000 you will not be allowed to continue because the sample is
          'too small to adequately measure.
          
          #INCLUDE "win32api.inc"
          
          GLOBAL gAction1    AS LONG
          GLOBAL gAction2    AS LONG
          GLOBAL g_Result    AS LONG
          GLOBAL gsX         AS STRING
          GLOBAL gsY         AS STRING
          GLOBAL gsZ         AS STRING
          GLOBAL Test1       AS DOUBLE
          GLOBAL Test2       AS DOUBLE
          GLOBAL giSync      AS LONG
          GLOBAL giIterate   AS LONG
          
          FUNCTION PBMAIN AS LONG
              LOCAL lsOutput        AS STRING
              LOCAL XC              AS LONG
              LOCAL Variance        AS DOUBLE
              LOCAL DeltaV          AS DOUBLE
              LOCAL Avg()           AS DOUBLE
              'LOCAL AvgTotalTest_1  AS DOUBLE
              'LOCAL AvgTotalTest_2  AS DOUBLE
              LOCAL FinalDet        AS DOUBLE
              LOCAL NotifyValue     AS LONG
              LOCAL SmallTest1      AS DOUBLE
              LOCAL SmallTest2      AS DOUBLE
          
              DIM AVG(1 TO 10, 1 TO 3)
          
              gsX = STRING$(80, "X")   'create the test string
              gsY = STRING$(80, "Y")   'create the test string
              gsZ = STRING$(80, "Z")   'create the test string
              giIterate = 1000         '<-- select your test iterations here (1000 is very speedy and fairly accurate)
          
              'Calculating the variance that is accepable
              IF giIterate >= 1000 THEN
                  DeltaV = giIterate - 1000
                  Variance = 0.0000320 + DeltaV * 6.1111 * EXP10(-10)
              ELSE
                  Variance = 0.0000320
              END IF
          
              SLEEP 2
          
              IF giIterate < 1000 THEN
                  ? "Sorry, the requested tests could not be run. giIterate is too low for an adequate sample."
                  GOTO CloseDown
              END IF
          
              FOR XC = 1 TO 10  'do 10 runs
          
                  LOCAL hThread1 AS DWORD
                  THREAD CREATE ProcessTest1(1) TO hThread1
                  THREAD CLOSE hThread1 TO hThread1
          
                  LOCAL hThread2 AS DWORD
                  THREAD CREATE ProcessTest2(1) TO hThread2
                  THREAD CLOSE hThread2 TO hThread2
          
                  SLEEP 10
          
                  giSync = 1
          
                  DO WHILE gAction1 = 1 OR gAction2 = 1
                      SLEEP 10
                  LOOP
                  g_Result = SetPriorityClass(GetCurrentProcess(), %NORMAL_PRIORITY_CLASS)
                  AVG(XC, 1) = Test1
                  AVG(XC, 2) = Test2
                  AVG(XC, 3) = ABS(Test1 - Test2)
          
              NEXT
          
              'find the smallest test values for the 10 samples
              SmallTest1 = AVG(1,1)
              SmallTest2 = AVG(1,2)
          
              FOR XC = 1 TO 10
                  IF AVG(XC,1) <> 0 AND AVG(XC,1) < SmallTest1 THEN
                      SmallTest1 = AVG(XC, 1)
                  END IF
              NEXT XC
          
              FOR XC = 1 TO 10
                  IF AVG(XC,2) <> 0 AND AVG(XC,2) < SmallTest2 THEN
                      SmallTest2 = AVG(XC, 2)
                  END IF
              NEXT XC
          
              lsOutput = _
                  "10 Runs Completed." + $CRLF + _
                  USING$("&##.#######", "Test 1 smallest loop time at " + STR$(giIterate * 10) + " iterations = ", SmallTest1) + $CRLF + _
                  USING$("&##.#######", "Test 2 smallest loop time at " + STR$(giIterate * 10) + " iterations = ", SmallTest2) + $CRLF + $CRLF + _
                  USING$("&##.#######", "The variance is ", ABS(SmallTest1 - SmallTest2)) + $CRLF
              IF AVG(1, 3) <= Variance THEN
                  lsOutput = lsOutput + "Not significant."
              ELSE
                  lsOutput = lsOutput + "Is significant."
              END IF
          
          
              'is one of the code samples faster or not?
              IF SmallTest1 = SmallTest2 THEN
                  NotifyValue = 0
                  FinalDet = 0
              END IF
              IF SmallTest1 > SmallTest2 THEN
                  NotifyValue = 1
                  FinalDet = SmallTest1/SmallTest2
              END IF
              IF SmallTest1 < SmallTest2 THEN
                  NotifyValue = 2
                  FinalDet = SmallTest2/SmallTest1
              END IF
          
              'determine which message to display
              SELECT CASE NotifyValue
                  CASE 0
                      lsOutput = lsOutput + $CRLF + $CRLF + _
                      "The tests did not show any difference in the code segments."
                  CASE 1
                      IF ABS(SmallTest1 - SmallTest2) <= Variance THEN
                          lsOutput = lsOutput + $CRLF + $CRLF + _
                          "The tests did not show any difference in the code segments."
                      ELSE
                          lsOutput = lsOutput + $CRLF + $CRLF + _
                          USING$("&##.#", "Code segment 2 is ", FinalDet) + " times faster than code segment 1."
                      END IF
                  CASE 2
                      IF ABS(SmallTest1 - SmallTest2) <= Variance THEN
                          lsOutput = lsOutput + $CRLF + $CRLF + _
                          "The tests did not show any difference in the code segments."
                      ELSE
                          lsOutput = lsOutput + $CRLF + $CRLF + _
                          USING$("&##.#", "Code segment 1 is ", FinalDet) + " times faster than code segment 2."
                      END IF
          
              END SELECT
          
              ? lsOutput
              CloseDown:
          END FUNCTION
          
          THREAD FUNCTION ProcessTest1(BYVAL yyy AS LONG) AS LONG
              LOCAL XA    AS LONG
              LOCAL lsA   AS STRING
              LOCAL Done  AS DOUBLE
              LOCAL Start AS DOUBLE
          
              gAction1 = 1
          
              CheckAgain:
              IF giSync = 1 THEN
                  lsA = ""
          
                  GOSUB DoProcess
          
                  gAction1 = 0
                  EXIT FUNCTION
              END IF
              GOTO CheckAgain
              EXIT FUNCTION
          
              DoProcess:
                  g_Result = SetPriorityClass(GetCurrentProcess(), %REALTIME_PRIORITY_CLASS)
          
                  Start = TIMER
                  FOR XA = 1 TO giIterate
                     'Put your code here
                      lsA = lsA + gsX + gsY + gsZ + $CRLF
                  NEXT
                  Done = TIMER
                  Test1 = (Done - Start)/giIterate
          
              RETURN
          
          END FUNCTION
          
          THREAD FUNCTION ProcessTest2(BYVAL yyy AS LONG) AS LONG
              LOCAL XA    AS LONG
              LOCAL lsA   AS STRING
              LOCAL Done  AS DOUBLE
              LOCAL Start AS DOUBLE
          
              gAction2 = 1
          
              CheckAgain:
              IF giSync = 1 THEN
                  lsA = ""
          
                  GOSUB DoProcess
          
                  gAction2 = 0
                  EXIT FUNCTION
              END IF
              GOTO CheckAgain
              EXIT FUNCTION
          
              DoProcess:
                  g_Result = SetPriorityClass(GetCurrentProcess(), %REALTIME_PRIORITY_CLASS)
          
                  Start = TIMER
                  FOR XA = 1 TO giIterate
                     'Put your code here
                      'lsA = lsA + gsX + gsY + gsZ + $CRLF
                      lsA = BUILD$(lsA, gsX, gsY, gsZ, $CRLF)
                      'NOTE: With BUILD$ "Generally speaking, the greater the number of parameters,
                      'the greater the increase in execution speed." Bob Zale
                      'Build or concatenate strings with very high efficiency.
          
                  NEXT
                  Done = TIMER
                  Test2 = (Done - Start)/giIterate
          
              RETURN
          
          END FUNCTION

          Comment


          • #6
            Why does this thread remind me of the recent one about coming up with new Random Number algorithms?

            (Are Jim and Ribeiro related?)

            Comment


            • #7
              This is Source Code Library, not the thread in Programming, but too!
              Dale

              Comment


              • #8
                PB_Benchmark Version 6
                Just to sum things up and show it can handle Addition, Division, and Multiplication code segments. lsA = lsA + gsX + gsY + gsX + $CRLF was left in the thread processing routines to make sure the thread processing time was adequate to assess the code segment. See "Put your code here."

                Code:
                #COMPILE EXE "PB_Benchmark_6.exe"
                #DIM ALL
                
                'Example showing how to perform testing for high speed processes
                'like addition, multiplication and division code segments.
                
                'PB_Benchmark app
                'designed for PBWIN 10.4 and J Roca includes
                'Released by: Jim Fritts on 30 JUL 2019
                
                'Development platform is:
                'Windows 10 version 1809.
                '9 year old Toshiba Satellite Laptop.
                
                'Object:
                'Compare the completion time for 2 different code segments.
                '    "See put your code here."
                'Run synchronized threads 10 times and present a final
                '    comparitive report for all 10 runs.
                'Provide a fairly stable platform that can be used to
                '    produce quick and reasonably correct results which
                '    will be validated over and over again.
                
                'My Methods:
                '(1) The threads were used to separate/individualize the tests
                '    from the main procedure so the main procedure would not
                '    interfere with the testing.
                '(2) A REALTIME priority was used to allow each thread to steal
                '    clock pulses from the other processes going on in the
                '    background.
                '(3) GOSUBs were used for higher speed processing rather than
                '    a call to an external subroutine and to limit access to
                '    them by other processes.
                '(4) Even though it is unused in this example;
                '    BUILD$(lsA, gsX, gsY, gsZ, $CRLF), is speedier than
                '    lsA + gsX + gsY + gsZ + $CRLF according to the documentation.
                '(5) Initial string assignments were placed outside the threads
                '    to promote smoother/uninhibited processing of the test
                '    procedures.
                '(6) Provide an integrated variance calculator to improve
                '    stability of the output data.
                '    NOTE:
                '    You may need to change the variance for your system.
                '    The currently acceptable variance for 1000 iterations is
                '    fixed at 0.0000320.
                '    If your iterations go below 1000 you will not be allowed
                '    to continue because the sample is too small to adequately
                '    measure.
                '(7) Use Parallel processing to promote concurrency.
                '    NOTE:
                '    Parallel processing forces routines to share cycles rather
                '    than run routines end to end.
                '    The problem with testing in a single thread (end to end) is
                '    that at different times different cycles are allocated so
                '    the first test may run quick while the following test may
                '    run slow or vice versa which leads to garbage results; in
                '    other words, not likely a good comparison between data sets.
                '
                '    In this particular case when stable timing is critical it
                '    is best to use parallelism to force concurrency.
                '    Accuracy depends on sharing CPU cycles.
                '    Thread synchronization is used for the start of each test.
                '    Each thread can finish whenever it is through testing.
                '(8) Use the lowest values of all the runs to do the final
                '    calculations. You could use a Median if you chose.
                '(9) Display an output for the User.
                '    NOTE:
                '    The individual loop time is an average value for 1000 iterations.
                '    The output does not appear until all tests are complete.
                
                'Additional Info"
                'TIMER
                ' Is a DOUBLE that is
                ' (+/- 4.19*10^-307 to 1.79*10^308) and
                ' 15 to 16 digits of precision.
                
                'BUILD$(lsA, gsX, gsY, gsZ, $CRLF) is approximately 3 to 5 times
                'faster than lsA + gsX + gsY + gsZ + $CRLF
                'When used as the code segments I get one of these (3.5, 4.0, 4.5)
                'as the result usually; but, mostly 4.0.
                
                'SLEEP 2 and SLEEP 10 are arbitray values placed in the main part
                'of the app and are used as transitonary to insure this:
                '1) The process of assigning values to strings does not interfere
                '   with the thread activity that follows.
                '2) Waiting for the threads to come alive so that the threads can
                '   be synchronized and begin processing at approximately the same
                '   time.
                '
                'Parallel processing is a different beast and not well known to this
                'forum. That's ok. Glad I could be part of introducing it here.
                
                
                #INCLUDE "win32api.inc"
                
                GLOBAL gAction1    AS LONG
                GLOBAL gAction2    AS LONG
                GLOBAL g_Result    AS LONG
                GLOBAL gsX         AS STRING
                GLOBAL gsY         AS STRING
                GLOBAL gsZ         AS STRING
                GLOBAL Test1       AS DOUBLE
                GLOBAL Test2       AS DOUBLE
                GLOBAL giSync      AS LONG
                GLOBAL giIterate   AS LONG
                GLOBAL gdA         AS DOUBLE
                GLOBAL gdB         AS DOUBLE
                GLOBAL gdC         AS DOUBLE
                
                FUNCTION PBMAIN AS LONG
                    LOCAL lsOutput        AS STRING
                    LOCAL XC              AS LONG
                    LOCAL Variance        AS DOUBLE
                    LOCAL DeltaV          AS DOUBLE
                    LOCAL AVG()           AS DOUBLE
                    LOCAL FinalDet        AS DOUBLE
                    LOCAL NotifyValue     AS LONG
                    LOCAL SmallTest1      AS DOUBLE
                    LOCAL SmallTest2      AS DOUBLE
                
                    DIM AVG(1 TO 10, 1 TO 3)
                
                    gsX = STRING$(80, "X")   'create the test string
                    gsY = STRING$(80, "Y")   'create the test string
                    gsZ = STRING$(80, "Z")   'create the test string
                    giIterate = 1000         '<-- select your test iterations here (1000 is very speedy and fairly accurate)
                    gdA = 12345678901234567890
                    gdB = 12345678901234567890
                    gdC = 12345678901234567890
                
                    'Calculating the variance that is accepable
                    IF giIterate > 1000 THEN
                        DeltaV = giIterate - 1000
                        Variance = 0.0000320 + DeltaV * 6.1111 * EXP10(-10)
                    ELSE
                        Variance = 0.0000320
                    END IF
                
                    SLEEP 2
                
                    IF giIterate < 1000 THEN
                        ? "Sorry, the requested tests could not be run. giIterate is too low for an adequate sample."
                        GOTO CloseDown
                    END IF
                
                    FOR XC = 1 TO 10  'do 10 runs
                
                        LOCAL hThread1 AS DWORD
                        THREAD CREATE ProcessTest1(1) TO hThread1
                        THREAD CLOSE hThread1 TO hThread1
                
                        LOCAL hThread2 AS DWORD
                        THREAD CREATE ProcessTest2(1) TO hThread2
                        THREAD CLOSE hThread2 TO hThread2
                
                        SLEEP 10
                
                        giSync = 1
                
                        DO WHILE gAction1 = 1 OR gAction2 = 1
                            SLEEP 10
                        LOOP
                        g_Result = SetPriorityClass(GetCurrentProcess(), %NORMAL_PRIORITY_CLASS)
                        AVG(XC, 1) = Test1
                        AVG(XC, 2) = Test2
                        AVG(XC, 3) = ABS(Test1 - Test2)
                
                    NEXT
                
                    'find the smallest test values for the 10 samples
                    SmallTest1 = AVG(1,1)
                    SmallTest2 = AVG(1,2)
                
                    FOR XC = 1 TO 10
                        IF AVG(XC,1) <> 0 AND AVG(XC,1) < SmallTest1 THEN
                            SmallTest1 = AVG(XC, 1)
                        END IF
                    NEXT XC
                
                    FOR XC = 1 TO 10
                        IF AVG(XC,2) <> 0 AND AVG(XC,2) < SmallTest2 THEN
                            SmallTest2 = AVG(XC, 2)
                        END IF
                    NEXT XC
                
                    lsOutput = _
                        "10 Runs Completed." + $CRLF + _
                        USING$("&##.#######", "Test 1 smallest loop time at " + STR$(giIterate * 10) + " iterations = ", SmallTest1) + $CRLF + _
                        USING$("&##.#######", "Test 2 smallest loop time at " + STR$(giIterate * 10) + " iterations = ", SmallTest2) + $CRLF + $CRLF + _
                        USING$("&##.#######", "The variance is ", ABS(SmallTest1 - SmallTest2)) + $CRLF
                    IF AVG(1, 3) <= Variance THEN
                        lsOutput = lsOutput + "Not significant."
                    ELSE
                        lsOutput = lsOutput + "Is significant."
                    END IF
                
                
                    'is one of the code samples faster or not?
                    IF SmallTest1 = SmallTest2 THEN
                        NotifyValue = 0
                        FinalDet = 0
                    END IF
                    IF SmallTest1 > SmallTest2 THEN
                        NotifyValue = 1
                        FinalDet = SmallTest1/SmallTest2
                    END IF
                    IF SmallTest1 < SmallTest2 THEN
                        NotifyValue = 2
                        FinalDet = SmallTest2/SmallTest1
                    END IF
                
                    'determine which message to display
                    SELECT CASE NotifyValue
                        CASE 0
                            lsOutput = lsOutput + $CRLF + $CRLF + _
                            "The tests did not show any difference in the code segments."
                        CASE 1
                            IF ABS(SmallTest1 - SmallTest2) <= Variance THEN
                                lsOutput = lsOutput + $CRLF + $CRLF + _
                                "The tests did not show any difference in the code segments."
                            ELSE
                                lsOutput = lsOutput + $CRLF + $CRLF + _
                                USING$("&##.#", "Code segment 2 is ", FinalDet) + " times faster than code segment 1."
                            END IF
                        CASE 2
                            IF ABS(SmallTest1 - SmallTest2) <= Variance THEN
                                lsOutput = lsOutput + $CRLF + $CRLF + _
                                "The tests did not show any difference in the code segments."
                            ELSE
                                lsOutput = lsOutput + $CRLF + $CRLF + _
                                USING$("&##.#", "Code segment 1 is ", FinalDet) + " times faster than code segment 2."
                            END IF
                
                    END SELECT
                
                    ? lsOutput
                    CloseDown:
                END FUNCTION
                
                THREAD FUNCTION ProcessTest1(BYVAL yyy AS LONG) AS LONG
                    LOCAL XA    AS LONG
                    LOCAL lsA   AS STRING
                    LOCAL Done  AS DOUBLE
                    LOCAL Start AS DOUBLE
                    LOCAL AA    AS DOUBLE
                    LOCAL XD    AS LONG
                
                    gAction1 = 1
                
                    CheckAgain:
                    IF giSync = 1 THEN
                        lsA = ""
                
                        GOSUB DoProcess
                
                        gAction1 = 0
                        EXIT FUNCTION
                    END IF
                    GOTO CheckAgain
                    EXIT FUNCTION
                
                    DoProcess:
                        g_Result = SetPriorityClass(GetCurrentProcess(), %REALTIME_PRIORITY_CLASS)
                
                        Start = TIMER
                        FOR XA = 1 TO giIterate
                           'Put your code here
                            lsA = lsA + gsX + gsY + gsZ + $CRLF
                            FOR XD = 1 TO 50
                                AA = AA + (gdA * gdB * gdC)/5555
                            NEXT XD
                        NEXT
                        Done = TIMER
                        Test1 = (Done - Start)/giIterate
                
                    RETURN
                
                END FUNCTION
                
                THREAD FUNCTION ProcessTest2(BYVAL yyy AS LONG) AS LONG
                    LOCAL XA    AS LONG
                    LOCAL lsA   AS STRING
                    LOCAL Done  AS DOUBLE
                    LOCAL Start AS DOUBLE
                    LOCAL AA    AS DOUBLE
                    LOCAL XD    AS LONG
                
                    gAction2 = 1
                
                    CheckAgain:
                    IF giSync = 1 THEN
                        lsA = ""
                
                        GOSUB DoProcess
                
                        gAction2 = 0
                        EXIT FUNCTION
                    END IF
                    GOTO CheckAgain
                    EXIT FUNCTION
                
                    DoProcess:
                        g_Result = SetPriorityClass(GetCurrentProcess(), %REALTIME_PRIORITY_CLASS)
                
                        Start = TIMER
                        FOR XA = 1 TO giIterate
                           'Put your code here
                            lsA = lsA + gsX + gsY + gsZ + $CRLF
                            'lsA = BUILD$(lsA, gsX, gsY, gsZ, $CRLF)
                            'NOTE: With BUILD$ "Generally speaking, the greater the number of parameters,
                            'the greater the increase in execution speed." Bob Zale
                            'Build or concatenate strings with very high efficiency.
                            FOR XD = 1 TO 10000
                                AA = AA + (gdA * gdB * gdC)/5555
                            NEXT XD
                
                        NEXT
                        Done = TIMER
                        Test2 = (Done - Start)/giIterate
                
                    RETURN
                
                END FUNCTION

                Comment


                • #9
                  PB_Benchmark Version 7
                  1) Replaced low speed timer TIMER with high speed timer TIX.
                  2) Automatically pulls the system base frequency from the registry.
                  3) Current example shows Test 1 to be 200 times faster than test 2.
                  4) The acceptable Variance was changed to 0.0000099 which is < 1/3 its previous value.
                  5) The improvements in this app were made possible by the work I did with Timer Test.

                  Click image for larger version  Name:	New Bitmap Image.jpg Views:	0 Size:	18.1 KB ID:	783665

                  Code:
                  #COMPILE EXE "PB_Benchmark_7.exe"
                  #DIM ALL
                  
                  'Example showing how to perform testing for high speed processes
                  'like addition, multiplication and division code segments.
                  
                  'PB_Benchmark app
                  'designed for PBWIN 10.4 and J Roca includes
                  'Released by: Jim Fritts on 30 JUL 2019
                  
                  'Development platform is:
                  'Windows 10 version 1809.
                  '9 year old Toshiba Satellite Laptop.
                  
                  'Object:
                  'Compare the completion time for 2 different code segments.
                  '    "See put your code here."
                  'Run synchronized threads 10 times and present a final
                  '    comparitive report for all 10 runs.
                  'Provide a fairly stable platform that can be used to
                  '    produce quick and reasonably correct results which
                  '    will be validated over and over again.
                  
                  'My Methods:
                  '(1) The threads were used to separate/individualize the tests
                  '    from the main procedure so the main procedure would not
                  '    interfere with the testing.
                  '(2) A REALTIME priority was used to allow each thread to steal
                  '    clock pulses from the other processes going on in the
                  '    background.
                  '(3) GOSUBs were used for higher speed processing rather than
                  '    a call to an external subroutine and to limit access to
                  '    them by other processes.
                  '(4) Even though it is unused in this example;
                  '    BUILD$(lsA, gsX, gsY, gsZ, $CRLF), is speedier than
                  '    lsA + gsX + gsY + gsZ + $CRLF according to the documentation.
                  '(5) Initial string assignments were placed outside the threads
                  '    to promote smoother/uninhibited processing of the test
                  '    procedures.
                  '(6) Provide an integrated variance calculator to improve
                  '    stability of the output data.
                  '    NOTE:
                  '    You may need to change the variance for your system.
                  '    The currently acceptable variance for 1000 iterations is
                  '    fixed at 0.0000320.
                  '    If your iterations go below 1000 you will not be allowed
                  '    to continue because the sample is too small to adequately
                  '    measure.
                  '(7) Use Parallel processing to promote concurrency.
                  '    NOTE:
                  '    Parallel processing forces routines to share cycles rather
                  '    than run routines end to end.
                  '    The problem with testing in a single thread (end to end) is
                  '    that at different times different cycles are allocated so
                  '    the first test may run quick while the following test may
                  '    run slow or vice versa which leads to garbage results; in
                  '    other words, not likely a good comparison between data sets.
                  '
                  '    In this particular case when stable timing is critical it
                  '    is best to use parallelism to force concurrency.
                  '    Accuracy depends on sharing CPU cycles.
                  '    Thread synchronization is used for the start of each test.
                  '    Each thread can finish whenever it is through testing.
                  '(8) Use the lowest values of all the runs to do the final
                  '    calculations. You could use a Median if you chose.
                  '(9) Display an output for the User.
                  '    NOTE:
                  '    The individual loop time is an average value for 1000 iterations.
                  '    The output does not appear until all tests are complete.
                  
                  'Additional Info"
                  'TIMER
                  ' Is a DOUBLE that is
                  ' (+/- 4.19*10^-307 to 1.79*10^308) and
                  ' 15 to 16 digits of precision.
                  
                  'BUILD$(lsA, gsX, gsY, gsZ, $CRLF) is approximately 3 to 5 times
                  'faster than lsA + gsX + gsY + gsZ + $CRLF
                  'When used as the code segments I get one of these (3.5, 4.0, 4.5)
                  'as the result usually; but, mostly 4.0.
                  
                  'SLEEP 2 and SLEEP 10 are arbitrary values placed in the main part
                  'of the app and are used as transitonary to insure this:
                  '1) The process of assigning values to strings does not interfere
                  '   with the thread activity that follows.
                  '2) Waiting for the threads to come alive so that the threads can
                  '   be synchronized and begin processing at approximately the same
                  '   time.
                  '
                  'Parallel processing is a different beast and not well known to this
                  'forum. That's ok. Glad I could be part of introducing it here.
                  
                  '06 AUG 2019
                  'Replaced low speed timer TIMER with high speed timer TIX.
                  'Automatically pulls the system base frequency from the registry.
                  'Current example shows Test 1 to be 200 times faster than test 2.
                  
                  #INCLUDE "win32api.inc"
                  
                  GLOBAL gAction1    AS LONG
                  GLOBAL gAction2    AS LONG
                  GLOBAL g_Result    AS LONG
                  GLOBAL gsX         AS STRING
                  GLOBAL gsY         AS STRING
                  GLOBAL gsZ         AS STRING
                  GLOBAL Test1       AS QUAD
                  GLOBAL Test2       AS QUAD
                  GLOBAL qFreq       AS QUAD
                  GLOBAL giSync      AS LONG
                  GLOBAL giIterate   AS LONG
                  GLOBAL gdA         AS DOUBLE
                  GLOBAL gdB         AS DOUBLE
                  GLOBAL gdC         AS DOUBLE
                  GLOBAL MyBaseFreq  AS DWORD
                  
                  FUNCTION PBMAIN AS LONG
                      LOCAL lsOutput        AS STRING
                      LOCAL XC              AS LONG
                      LOCAL NotifyValue     AS LONG
                      LOCAL Variance        AS DOUBLE
                      LOCAL AVG()           AS DOUBLE
                      LOCAL FinalDet        AS QUAD
                      LOCAL SmallTest1      AS DOUBLE
                      LOCAL SmallTest2      AS DOUBLE
                      LOCAL DeltaSmallTest  AS DOUBLE
                  
                      DIM AVG(1 TO 10, 1 TO 2)
                  
                      LOCAL sData AS STRING
                      regDataGet(%HKEY_LOCAL_MACHINE, "HARDWARE\DESCRIPTION\System\CentralProcessor\0", "~MHZ", sData)
                  
                      'Mine is 0x00000893 (2195) dword
                      MyBaseFreq = VAL(sData) * 1000000
                  
                      gsX = STRING$(80, "X")   'create the test string
                      gsY = STRING$(80, "Y")   'create the test string
                      gsZ = STRING$(80, "Z")   'create the test string
                      giIterate = 1000         '<-- select your test iterations here (1000 is very speedy and fairly accurate)
                      gdA = 12345678901234567890
                      gdB = 12345678901234567890
                      gdC = 12345678901234567890
                  
                      Variance = 0.0000099
                  
                      SLEEP 2
                  
                      IF giIterate < 1000 THEN
                          ? "Sorry, the requested tests could not be run. giIterate is too low for an adequate sample."
                          GOTO CloseDown
                      END IF
                  
                      FOR XC = 1 TO 10  'do 10 runs
                  
                          LOCAL hThread1 AS DWORD
                          THREAD CREATE ProcessTest1(1) TO hThread1
                          THREAD CLOSE hThread1 TO hThread1
                  
                          LOCAL hThread2 AS DWORD
                          THREAD CREATE ProcessTest2(1) TO hThread2
                          THREAD CLOSE hThread2 TO hThread2
                  
                          SLEEP 10
                  
                          giSync = 1
                  
                          DO WHILE gAction1 = 1 OR gAction2 = 1
                              SLEEP 10
                          LOOP
                          g_Result = SetPriorityClass(GetCurrentProcess(), %NORMAL_PRIORITY_CLASS)
                          AVG(XC, 1) = Test1
                          AVG(XC, 2) = Test2
                  
                      NEXT
                  
                      'find the smallest test values for the 10 samples
                      SmallTest1 = AVG(1,1)
                      SmallTest2 = AVG(1,2)
                  
                      FOR XC = 1 TO 10
                          IF AVG(XC,1) <> 0 AND AVG(XC,1) < SmallTest1 THEN
                              SmallTest1 = AVG(XC, 1)
                          END IF
                      NEXT XC
                  
                      FOR XC = 1 TO 10
                          IF AVG(XC,2) <> 0 AND AVG(XC,2) < SmallTest2 THEN
                              SmallTest2 = AVG(XC, 2)
                          END IF
                      NEXT XC
                  
                      SmallTest1 = SmallTest1/MyBaseFreq
                      SmallTest2 = SmallTest2/MyBaseFreq
                      DeltaSmallTest = ABS(SmallTest2 - SmallTest1)
                  
                      lsOutput = _
                          "10 Runs Completed." + $CRLF + _
                          USING$("&##.#######", "Test 1 smallest loop time at " + STR$(giIterate * 10) + " iterations = ", SmallTest1) + $CRLF + _
                          USING$("&##.#######", "Test 2 smallest loop time at " + STR$(giIterate * 10) + " iterations = ", SmallTest2) + $CRLF + $CRLF + _
                          USING$("&##.#######", "The variance is ", DeltaSmallTest) + $CRLF
                  
                      IF DeltaSmallTest <= Variance THEN
                          lsOutput = lsOutput + "Not significant."
                      ELSE
                          lsOutput = lsOutput + "Is significant."
                      END IF
                  
                  
                      'is one of the code samples faster or not?
                      IF SmallTest1 = SmallTest2 THEN
                          NotifyValue = 0
                          FinalDet = 0
                      END IF
                      IF SmallTest1 > SmallTest2 THEN
                          NotifyValue = 1
                          FinalDet = SmallTest1/SmallTest2
                      END IF
                      IF SmallTest1 < SmallTest2 THEN
                          NotifyValue = 2
                          FinalDet = SmallTest2/SmallTest1
                      END IF
                  
                      'determine which message to display
                      SELECT CASE NotifyValue
                          CASE 0
                              lsOutput = lsOutput + $CRLF + $CRLF + _
                              "The tests did not show any difference in the code segments."
                          CASE 1
                              IF ABS(SmallTest1 - SmallTest2) <= Variance THEN
                                  lsOutput = lsOutput + $CRLF + $CRLF + _
                                  "The tests did not show any difference in the code segments."
                              ELSE
                                  lsOutput = lsOutput + $CRLF + $CRLF + _
                                  USING$("&##.#", "Code segment 2 is ", FinalDet) + " times faster than code segment 1."
                              END IF
                          CASE 2
                              IF ABS(SmallTest1 - SmallTest2) <= Variance THEN
                                  lsOutput = lsOutput + $CRLF + $CRLF + _
                                  "The tests did not show any difference in the code segments."
                              ELSE
                                  lsOutput = lsOutput + $CRLF + $CRLF + _
                                  USING$("&##.#", "Code segment 1 is ", FinalDet) + " times faster than code segment 2."
                              END IF
                  
                      END SELECT
                  
                      ? lsOutput
                      CloseDown:
                  END FUNCTION
                  
                  'Thanks to Pierre Bellisle
                  FUNCTION regDataGet(hMainKey AS DWORD, sKeyName AS STRING, sValueName AS STRING, sData AS STRING) AS LONG
                   LOCAL Retval    AS LONG
                   LOCAL dwSize    AS DWORD
                   LOCAL hKey      AS DWORD
                   LOCAL dwRegType AS DWORD
                  
                   sData = ""
                   IF RegOpenKeyExA(hMainKey, BYVAL STRPTR(sKeyName), BYVAL %NULL, %KEY_READ, hKey) = %ERROR_SUCCESS THEN
                     Retval = RegQueryValueExA(hKey, BYVAL STRPTR(sValueName), BYVAL %NULL, _
                                              BYVAL %NULL, BYVAL %NULL, dwSize)
                     IF Retval = %ERROR_SUCCESS THEN
                       sData = NUL$(dwSize)
                       Retval = RegQueryValueExA(hKey, BYVAL STRPTR(sValueName), BYVAL %NULL, _
                                                dwRegType, BYVAL STRPTR(sData), dwSize)
                       SELECT CASE dwRegType
                         CASE %REG_SZ, %REG_EXPAND_SZ, %REG_MULTI_SZ
                           sData = RTRIM$(sData, $NUL) 'Remove one or two ending $NUL
                         CASE %REG_DWORD
                           sData = FORMAT$(CVDWD(sData)) 'Convert dword to string
                         CASE %REG_QWORD, %REG_QWORD_LITTLE_ENDIAN
                           sData = FORMAT$(CVQ(sData)) 'Convert quad to string
                       END SELECT
                     END IF
                     RegCloseKey(hKey)
                   END IF
                   FUNCTION = Retval
                  
                  END FUNCTION
                  
                  
                  THREAD FUNCTION ProcessTest1(BYVAL yyy AS LONG) AS LONG
                      LOCAL XA    AS LONG
                      LOCAL lsA   AS STRING
                      LOCAL XD    AS LONG
                      LOCAL Done  AS QUAD
                      LOCAL Start AS QUAD
                      LOCAL AA    AS QUAD
                  
                      gAction1 = 1
                  
                      CheckAgain:
                      IF giSync = 1 THEN
                          lsA = ""
                  
                          GOSUB DoProcess
                  
                          gAction1 = 0
                          EXIT FUNCTION
                      END IF
                      GOTO CheckAgain
                      EXIT FUNCTION
                  
                      DoProcess:
                          g_Result = SetPriorityClass(GetCurrentProcess(), %REALTIME_PRIORITY_CLASS)
                  
                          TIX Start
                          FOR XA = 1 TO giIterate
                             'Put your code here
                              'lsA = lsA + gsX + gsY + gsZ + $CRLF  '(for sample test)
                  
                              FOR XD = 1 TO 50
                                  AA = AA + (gdA * gdB * gdC)/5555
                              NEXT XD
                  
                          NEXT
                          TIX Done
                          Test1 = (Done - Start)/giIterate
                  
                      RETURN
                  
                  END FUNCTION
                  
                  THREAD FUNCTION ProcessTest2(BYVAL yyy AS LONG) AS LONG
                      LOCAL XA    AS LONG
                      LOCAL lsA   AS STRING
                      LOCAL XD    AS LONG
                      LOCAL Done  AS QUAD
                      LOCAL Start AS QUAD
                      LOCAL AA    AS QUAD
                  
                      gAction2 = 1
                  
                      CheckAgain:
                      IF giSync = 1 THEN
                          lsA = ""
                  
                          GOSUB DoProcess
                  
                          gAction2 = 0
                          EXIT FUNCTION
                      END IF
                      GOTO CheckAgain
                      EXIT FUNCTION
                  
                      DoProcess:
                          g_Result = SetPriorityClass(GetCurrentProcess(), %REALTIME_PRIORITY_CLASS)
                  
                          TIX Start
                          FOR XA = 1 TO giIterate
                             'Put your code here
                              'lsA = lsA + gsX + gsY + gsZ + $CRLF  'same as test 1 loops  (for sample test)
                  
                              'lsA = BUILD$(lsA, gsX, gsY, gsZ, $CRLF) '(for comparison test)
                              'NOTE: With BUILD$ "Generally speaking, the greater the number of parameters,
                              'the greater the increase in execution speed." Bob Zale
                              'Build or concatenate strings with very high efficiency.
                  
                              'FOR XD = 1 TO 50   'same as test 1 loops  (for sample test)
                              '    AA = AA + (gdA * gdB * gdC)/5555
                              'NEXT XD
                  
                              FOR XD = 1 TO 10000 '200 times the loops in test 1 (for comparison test)
                                  AA = AA + (gdA * gdB * gdC)/5555
                              NEXT XD
                  
                          NEXT
                          TIX Done
                          Test2 = (Done - Start)/giIterate
                  
                      RETURN
                  
                  END FUNCTION
                  Last edited by Jim Fritts; 7 Aug 2019, 09:57 AM.

                  Comment


                  • #10
                    Code Updates:
                    Changes to PB_BenchMark 7 changed 2020-MAR-12
                    GLOBAL Test1 AS DOUBLE
                    GLOBAL Test2 AS DOUBLE

                    LOCAL FinalDet AS DOUBLE
                    Variance = 0.0000050

                    Comment


                    • #11
                      Code updates:
                      Code:
                          'determine which message to display
                          SELECT CASE NotifyValue
                              CASE 0
                                  lsOutput = lsOutput + $CRLF + $CRLF + _
                                  "The tests did not show any difference in the code segments."
                              CASE 1
                                  IF ABS(SmallTest1 - SmallTest2) <= Variance THEN
                                      lsOutput = lsOutput + $CRLF + $CRLF + _
                                      "The tests did not show any significant difference in the code segments"
                                      IF SmallTest1 < SmallTest2 THEN
                                          lsOutput = lsOutput + $CRLF + _
                                          "but code segment 1 was slightly faster than code segment 2."
                                      END IF
                                      IF SmallTest2 < SmallTest1 THEN
                                          lsOutput = lsOutput + $CRLF + _
                                          "but code segment 2 was slightly faster than code segment 1."
                                      END IF
                                  ELSE
                                      lsOutput = lsOutput + $CRLF + $CRLF + _
                                      USING$("&##.##", "Code segment 2 is ", FinalDet) + " times faster than code segment 1."
                                  END IF
                              CASE 2
                                  IF ABS(SmallTest1 - SmallTest2) <= Variance THEN
                                      lsOutput = lsOutput + $CRLF + $CRLF + _
                                      "The tests did not show any significant difference in the code segments"
                                      IF SmallTest1 < SmallTest2 THEN
                                          lsOutput = lsOutput + $CRLF + _
                                          "but code segment 1 was slightly faster than code segment 2."
                                      END IF
                                      IF SmallTest2 < SmallTest1 THEN
                                          lsOutput = lsOutput + $CRLF + _
                                          "but code segment 2 was slightly faster than code segment 1."
                                      END IF
                                  ELSE
                                      lsOutput = lsOutput + $CRLF + $CRLF + _
                                      USING$("&##.##", "Code segment 1 is ", FinalDet) + " times faster than code segment 2."
                                  END IF
                      
                          END SELECT
                      Variance is now 0.0000020

                      Comment


                      • #12
                        PB_Benchmark_8

                        Code:
                        #COMPILE EXE "PB_Benchmark_8.exe"
                        #DIM ALL
                        '#REGISTER ALL
                        
                        $appName = "PB_Benchmark_8"
                        
                        
                        'Example showing how to perform testing for high speed processes
                        'like addition, multiplication and division code segments.
                        
                        'PB_Benchmark app
                        'designed for PBWIN 10.4 and J Roca includes
                        'Released by: Jim Fritts on 30 JUL 2019
                        
                        'Development platform is:
                        'Windows 10 version 1809.
                        '9 year old Toshiba Satellite Laptop.
                        
                        'Object:
                        'Compare the completion time for 2 different code segments.
                        '    "See put your code here."
                        'Run synchronized threads 10 times and present a final
                        '    comparitive report for all 10 runs.
                        'Provide a fairly stable platform that can be used to
                        '    produce quick and reasonably correct results which
                        '    will be validated over and over again.
                        
                        'My Methods:
                        '(1) The threads were used to separate/individualize the tests
                        '    from the main procedure so the main procedure would not
                        '    interfere with the testing.
                        '(2) A REALTIME priority was used to allow each thread to steal
                        '    clock pulses from the other processes going on in the
                        '    background.
                        '(3) GOSUBs were used for higher speed processing rather than
                        '    a call to an external subroutine and to limit access to
                        '    them by other processes.
                        '(4) Even though it is unused in this example;
                        '    BUILD$(lsA, gsX, gsY, gsZ, $CRLF), is speedier than
                        '    lsA + gsX + gsY + gsZ + $CRLF according to the documentation.
                        '(5) Initial string assignments were placed outside the threads
                        '    to promote smoother/uninhibited processing of the test
                        '    procedures.
                        '(6) Provide an integrated variance calculator to improve
                        '    stability of the output data.
                        '    NOTE:
                        '    You may need to change the variance for your system.
                        '    The currently acceptable variance for 1000 iterations is
                        '    fixed at 0.0000320.
                        '    If your iterations go below 1000 you will not be allowed
                        '    to continue because the sample is too small to adequately
                        '    measure.
                        '(7) Use Parallel processing to promote concurrency.
                        '    NOTE:
                        '    Parallel processing forces routines to share cycles rather
                        '    than run routines end to end.
                        '    The problem with testing in a single thread (end to end) is
                        '    that at different times different cycles are allocated so
                        '    the first test may run quick while the following test may
                        '    run slow or vice versa which leads to garbage results; in
                        '    other words, not likely a good comparison between data sets.
                        '
                        '    In this particular case when stable timing is critical it
                        '    is best to use parallelism to force concurrency.
                        '    Accuracy depends on sharing CPU cycles.
                        '    Thread synchronization is used for the start of each test.
                        '    Each thread can finish whenever it is through testing.
                        '(8) Use the lowest values of all the runs to do the final
                        '    calculations. You could use a Median if you chose.
                        '(9) Display an output for the User.
                        '    NOTE:
                        '    The individual loop time is an average value for 1000 iterations.
                        '    The output does not appear until all tests are complete.
                        '(10) Added extracted code segments to reduce compile time.
                        
                        'Additional Info"
                        'TIMER
                        ' Is a DOUBLE that is
                        ' (+/- 4.19*10^-307 to 1.79*10^308) and
                        ' 15 to 16 digits of precision.
                        
                        'Testing with no other applications running....
                        'BUILD$(lsA, gsX, gsY, gsZ, $CRLF) is approximately 3 to 4 times
                        'faster than lsA + gsX + gsY + gsZ + $CRLF
                        'When used as the code segments I get one of these (3.2 to 3.9)
                        'as the result usually; but, mostly 3.5.
                        
                        'SLEEP 2 and SLEEP 10 are arbitrary values placed in the main part
                        'of the app and are used as transitonary to insure this:
                        '1) The process of assigning values to strings does not interfere
                        '   with the thread activity that follows.
                        '2) Waiting for the threads to come alive so that the threads can
                        '   be synchronized and begin processing at approximately the same
                        '   time.
                        '3) Waiting on both threads to finish before processing the thread data.
                        '
                        'Parallel processing is a different beast and not well known to this
                        'forum. That's ok. Glad I could be part of introducing it here.
                        
                        '06 AUG 2019
                        '1) Replaced low speed timer TIMER with high speed timer TIX.
                        '2) Automatically pulls the system base frequency from the registry.
                        '3) Current example shows Test 1 to be 200 times faster than test 2.
                        '4) The acceptable Variance was changed to 0.0000099 which is < 1/3 its previous value.
                        '5) The improvements in this app were made possible by the work I did with Timer Test.
                        
                        '28 JUN 2020
                        'Added accelerator thanks to David Roberts
                        '#INCLUDE "win32api.inc"
                        'All functions were extracted from includes.
                        
                        '//////////////////// Begin Code Extraction
                        %TRUE  = 1
                        %FALSE = 0
                        %NULL  = 0
                        
                        $NULL     = CHR$(0)
                        
                        %HKEY_LOCAL_MACHINE     = &H80000002???
                        
                        '//
                        '//  The following are masks for the predefined standard access types
                        '//
                        
                        %DELETE                   = &H00010000???
                        %READ_CONTROL             = &H00020000???
                        %WRITE_DAC                = &H00040000???
                        %WRITE_OWNER              = &H00080000???
                        %SYNCHRONIZE              = &H00100000???
                        
                        %STANDARD_RIGHTS_REQUIRED = &H000F0000???
                        
                        %STANDARD_RIGHTS_READ     = %READ_CONTROL
                        %STANDARD_RIGHTS_WRITE    = %READ_CONTROL
                        %STANDARD_RIGHTS_EXECUTE  = %READ_CONTROL
                        
                        %STANDARD_RIGHTS_ALL      = &H001F0000???
                        
                        %SPECIFIC_RIGHTS_ALL      = &H0000FFFF???
                        
                        '//
                        '// Registry Specific Access Rights.
                        '//
                        
                        %KEY_QUERY_VALUE         = &H0001???
                        %KEY_SET_VALUE           = &H0002???
                        %KEY_CREATE_SUB_KEY      = &H0004???
                        %KEY_ENUMERATE_SUB_KEYS  = &H0008???
                        %KEY_NOTIFY              = &H0010???
                        %KEY_CREATE_LINK         = &H0020???
                        %KEY_WOW64_32KEY         = &H0200???
                        %KEY_WOW64_64KEY         = &H0100???
                        %KEY_WOW64_RES           = &H0300???
                        
                        
                        %KEY_READ               = %STANDARD_RIGHTS_READ OR %KEY_QUERY_VALUE OR %KEY_ENUMERATE_SUB_KEYS OR %KEY_NOTIFY AND (NOT %SYNCHRONIZE)
                        %KEY_WRITE              = %STANDARD_RIGHTS_WRITE OR %KEY_SET_VALUE OR %KEY_CREATE_SUB_KEY AND (NOT %SYNCHRONIZE)
                        %KEY_EXECUTE            = %KEY_READ
                        %KEY_ALL_ACCESS         = %STANDARD_RIGHTS_ALL OR %KEY_QUERY_VALUE OR %KEY_SET_VALUE OR %KEY_CREATE_SUB_KEY OR %KEY_ENUMERATE_SUB_KEYS OR %KEY_NOTIFY OR %KEY_CREATE_LINK AND (NOT %SYNCHRONIZE)
                        
                        ' The configuration registry database operation completed successfully.
                        %ERROR_SUCCESS                    = 0&
                        
                        %ERROR_INVALID_FUNCTION           = 1&     ' dderror
                        %ERROR_FILE_NOT_FOUND             = 2&
                        %ERROR_PATH_NOT_FOUND             = 3&
                        %ERROR_TOO_MANY_OPEN_FILES        = 4&
                        %ERROR_ACCESS_DENIED              = 5&
                        %ERROR_INVALID_HANDLE             = 6&
                        %ERROR_ARENA_TRASHED              = 7&
                        %ERROR_NOT_ENOUGH_MEMORY          = 8&     ' dderror
                        %ERROR_INVALID_BLOCK              = 9&
                        %ERROR_BAD_ENVIRONMENT            = 10&
                        %ERROR_BAD_FORMAT                 = 11&
                        %ERROR_INVALID_ACCESS             = 12&
                        %ERROR_INVALID_DATA               = 13&
                        %ERROR_OUTOFMEMORY                = 14&
                        %ERROR_INVALID_DRIVE              = 15&
                        %ERROR_CURRENT_DIRECTORY          = 16&
                        %ERROR_NOT_SAME_DEVICE            = 17&
                        %ERROR_NO_MORE_FILES              = 18&
                        %ERROR_WRITE_PROTECT              = 19&
                        %ERROR_BAD_UNIT                   = 20&
                        %ERROR_NOT_READY                  = 21&
                        %ERROR_BAD_COMMAND                = 22&
                        %ERROR_CRC                        = 23&
                        %ERROR_BAD_LENGTH                 = 24&
                        %ERROR_SEEK                       = 25&
                        %ERROR_NOT_DOS_DISK               = 26&
                        %ERROR_SECTOR_NOT_FOUND           = 27&
                        %ERROR_OUT_OF_PAPER               = 28&
                        %ERROR_WRITE_FAULT                = 29&
                        %ERROR_READ_FAULT                 = 30&
                        %ERROR_GEN_FAILURE                = 31&
                        %ERROR_SHARING_VIOLATION          = 32&
                        %ERROR_LOCK_VIOLATION             = 33&
                        %ERROR_WRONG_DISK                 = 34&
                        %ERROR_SHARING_BUFFER_EXCEEDED    = 36&
                        %ERROR_HANDLE_EOF                 = 38&
                        %ERROR_HANDLE_DISK_FULL           = 39&
                        %ERROR_NOT_SUPPORTED              = 50&
                        %ERROR_REM_NOT_LIST               = 51&
                        %ERROR_DUP_NAME                   = 52&
                        %ERROR_BAD_NETPATH                = 53&
                        %ERROR_NETWORK_BUSY               = 54&
                        %ERROR_DEV_NOT_EXIST              = 55&     ' dderror
                        %ERROR_TOO_MANY_CMDS              = 56&
                        %ERROR_ADAP_HDW_ERR               = 57&
                        %ERROR_BAD_NET_RESP               = 58&
                        %ERROR_UNEXP_NET_ERR              = 59&
                        %ERROR_BAD_REM_ADAP               = 60&
                        %ERROR_PRINTQ_FULL                = 61&
                        %ERROR_NO_SPOOL_SPACE             = 62&
                        %ERROR_PRINT_CANCELLED            = 63&
                        %ERROR_NETNAME_DELETED            = 64&
                        %ERROR_NETWORK_ACCESS_DENIED      = 65&
                        %ERROR_BAD_DEV_TYPE               = 66&
                        %ERROR_BAD_NET_NAME               = 67&
                        %ERROR_TOO_MANY_NAMES             = 68&
                        %ERROR_TOO_MANY_SESS              = 69&
                        %ERROR_SHARING_PAUSED             = 70&
                        %ERROR_REQ_NOT_ACCEP              = 71&
                        %ERROR_REDIR_PAUSED               = 72&
                        %ERROR_FILE_EXISTS                = 80&
                        %ERROR_CANNOT_MAKE                = 82&
                        %ERROR_FAIL_I24                   = 83&
                        %ERROR_OUT_OF_STRUCTURES          = 84&
                        %ERROR_ALREADY_ASSIGNED           = 85&
                        %ERROR_INVALID_PASSWORD           = 86&
                        %ERROR_INVALID_PARAMETER          = 87&     ' dderror
                        %ERROR_NET_WRITE_FAULT            = 88&
                        %ERROR_NO_PROC_SLOTS              = 89&
                        %ERROR_TOO_MANY_SEMAPHORES        = 100&
                        %ERROR_EXCL_SEM_ALREADY_OWNED     = 101&
                        %ERROR_SEM_IS_SET                 = 102&
                        %ERROR_TOO_MANY_SEM_REQUESTS      = 103&
                        %ERROR_INVALID_AT_INTERRUPT_TIME  = 104&
                        %ERROR_SEM_OWNER_DIED             = 105&
                        %ERROR_SEM_USER_LIMIT             = 106&
                        %ERROR_DISK_CHANGE                = 107&
                        %ERROR_DRIVE_LOCKED               = 108&
                        %ERROR_BROKEN_PIPE                = 109&
                        %ERROR_OPEN_FAILED                = 110&
                        %ERROR_BUFFER_OVERFLOW            = 111&
                        %ERROR_DISK_FULL                  = 112&
                        %ERROR_NO_MORE_SEARCH_HANDLES     = 113&
                        %ERROR_INVALID_TARGET_HANDLE      = 114&
                        %ERROR_INVALID_CATEGORY           = 117&
                        %ERROR_INVALID_VERIFY_SWITCH      = 118&
                        %ERROR_BAD_DRIVER_LEVEL           = 119&
                        %ERROR_CALL_NOT_IMPLEMENTED       = 120&
                        %ERROR_SEM_TIMEOUT                = 121&
                        %ERROR_INSUFFICIENT_BUFFER        = 122&     ' dderror
                        %ERROR_INVALID_NAME               = 123&     ' dderror
                        %ERROR_INVALID_LEVEL              = 124&
                        %ERROR_NO_VOLUME_LABEL            = 125&
                        %ERROR_MOD_NOT_FOUND              = 126&
                        %ERROR_PROC_NOT_FOUND             = 127&
                        %ERROR_WAIT_NO_CHILDREN           = 128&
                        %ERROR_CHILD_NOT_COMPLETE         = 129&
                        %ERROR_DIRECT_ACCESS_HANDLE       = 130&
                        %ERROR_NEGATIVE_SEEK              = 131&
                        %ERROR_SEEK_ON_DEVICE             = 132&
                        %ERROR_IS_JOIN_TARGET             = 133&
                        %ERROR_IS_JOINED                  = 134&
                        %ERROR_IS_SUBSTED                 = 135&
                        %ERROR_NOT_JOINED                 = 136&
                        %ERROR_NOT_SUBSTED                = 137&
                        %ERROR_JOIN_TO_JOIN               = 138&
                        %ERROR_SUBST_TO_SUBST             = 139&
                        %ERROR_JOIN_TO_SUBST              = 140&
                        %ERROR_SUBST_TO_JOIN              = 141&
                        %ERROR_BUSY_DRIVE                 = 142&
                        %ERROR_SAME_DRIVE                 = 143&
                        %ERROR_DIR_NOT_ROOT               = 144&
                        %ERROR_DIR_NOT_EMPTY              = 145&
                        %ERROR_IS_SUBST_PATH              = 146&
                        %ERROR_IS_JOIN_PATH               = 147&
                        %ERROR_PATH_BUSY                  = 148&
                        %ERROR_IS_SUBST_TARGET            = 149&
                        %ERROR_SYSTEM_TRACE               = 150&
                        %ERROR_INVALID_EVENT_COUNT        = 151&
                        %ERROR_TOO_MANY_MUXWAITERS        = 152&
                        %ERROR_INVALID_LIST_FORMAT        = 153&
                        %ERROR_LABEL_TOO_LONG             = 154&
                        %ERROR_TOO_MANY_TCBS              = 155&
                        %ERROR_SIGNAL_REFUSED             = 156&
                        %ERROR_DISCARDED                  = 157&
                        %ERROR_NOT_LOCKED                 = 158&
                        %ERROR_BAD_THREADID_ADDR          = 159&
                        %ERROR_BAD_ARGUMENTS              = 160&
                        %ERROR_BAD_PATHNAME               = 161&
                        %ERROR_SIGNAL_PENDING             = 162&
                        %ERROR_MAX_THRDS_REACHED          = 164&
                        %ERROR_LOCK_FAILED                = 167&
                        %ERROR_BUSY                       = 170&
                        %ERROR_CANCEL_VIOLATION           = 173&
                        %ERROR_ATOMIC_LOCKS_NOT_SUPPORTED = 174&
                        %ERROR_INVALID_SEGMENT_NUMBER     = 180&
                        %ERROR_INVALID_ORDINAL            = 182&
                        %ERROR_ALREADY_EXISTS             = 183&
                        %ERROR_INVALID_FLAG_NUMBER        = 186&
                        %ERROR_SEM_NOT_FOUND              = 187&
                        %ERROR_INVALID_STARTING_CODESEG   = 188&
                        %ERROR_INVALID_STACKSEG           = 189&
                        %ERROR_INVALID_MODULETYPE         = 190&
                        %ERROR_INVALID_EXE_SIGNATURE      = 191&
                        %ERROR_EXE_MARKED_INVALID         = 192&
                        %ERROR_BAD_EXE_FORMAT             = 193&
                        %ERROR_ITERATED_DATA_EXCEEDS_64k  = 194&
                        %ERROR_INVALID_MINALLOCSIZE       = 195&
                        %ERROR_DYNLINK_FROM_INVALID_RING  = 196&
                        %ERROR_IOPL_NOT_ENABLED           = 197&
                        %ERROR_INVALID_SEGDPL             = 198&
                        %ERROR_AUTODATASEG_EXCEEDS_64k    = 199&
                        %ERROR_RING2SEG_MUST_BE_MOVABLE   = 200&
                        %ERROR_RELOC_CHAIN_XEEDS_SEGLIM   = 201&
                        %ERROR_INFLOOP_IN_RELOC_CHAIN     = 202&
                        %ERROR_ENVVAR_NOT_FOUND           = 203&
                        %ERROR_NO_SIGNAL_SENT             = 205&
                        %ERROR_FILENAME_EXCED_RANGE       = 206&
                        %ERROR_RING2_STACK_IN_USE         = 207&
                        %ERROR_META_EXPANSION_TOO_LONG    = 208&
                        %ERROR_INVALID_SIGNAL_NUMBER      = 209&
                        %ERROR_THREAD_1_INACTIVE          = 210&
                        %ERROR_LOCKED                     = 212&
                        %ERROR_TOO_MANY_MODULES           = 214&
                        %ERROR_NESTING_NOT_ALLOWED        = 215&
                        %ERROR_EXE_MACHINE_TYPE_MISMATCH  = 216&
                        %ERROR_BAD_PIPE                   = 230&
                        %ERROR_PIPE_BUSY                  = 231&
                        %ERROR_NO_DATA                    = 232&
                        %ERROR_PIPE_NOT_CONNECTED         = 233&
                        %ERROR_MORE_DATA                  = 234&     ' dderror
                        %ERROR_VC_DISCONNECTED            = 240&
                        %ERROR_INVALID_EA_NAME            = 254&
                        %ERROR_EA_LIST_INCONSISTENT       = 255&
                        %WAIT_TIMEOUT                     = 258&
                        %ERROR_NO_MORE_ITEMS              = 259&
                        %ERROR_CANNOT_COPY                = 266&
                        %ERROR_DIRECTORY                  = 267&
                        %ERROR_EAS_DIDNT_FIT              = 275&
                        %ERROR_EA_FILE_CORRUPT            = 276&
                        %ERROR_EA_TABLE_FULL              = 277&
                        %ERROR_INVALID_EA_HANDLE          = 278&
                        %ERROR_EAS_NOT_SUPPORTED          = 282&
                        %ERROR_NOT_OWNER                  = 288&
                        %ERROR_TOO_MANY_POSTS             = 298&
                        %ERROR_PARTIAL_COPY               = 299&
                        %ERROR_OPLOCK_NOT_GRANTED         = 300&
                        %ERROR_INVALID_OPLOCK_PROTOCOL    = 301&
                        %ERROR_MR_MID_NOT_FOUND           = 317&
                        %ERROR_INVALID_ADDRESS            = 487&
                        %ERROR_ARITHMETIC_OVERFLOW        = 534&
                        %ERROR_PIPE_CONNECTED             = 535&
                        %ERROR_PIPE_LISTENING             = 536&
                        %ERROR_EA_ACCESS_DENIED           = 994&
                        %ERROR_OPERATION_ABORTED          = 995&
                        %ERROR_IO_INCOMPLETE              = 996&
                        %ERROR_IO_PENDING                 = 997&     ' dderror
                        %ERROR_NOACCESS                   = 998&
                        %ERROR_SWAPERROR                  = 999&
                        %ERROR_STACK_OVERFLOW             = 1001&
                        %ERROR_INVALID_MESSAGE            = 1002&
                        %ERROR_CAN_NOT_COMPLETE           = 1003&
                        %ERROR_INVALID_FLAGS              = 1004&
                        %ERROR_UNRECOGNIZED_VOLUME        = 1005&
                        %ERROR_FILE_INVALID               = 1006&
                        %ERROR_FULLSCREEN_MODE            = 1007&
                        %ERROR_NO_TOKEN                   = 1008&
                        %ERROR_BADDB                      = 1009&
                        %ERROR_BADKEY                     = 1010&
                        %ERROR_CANTOPEN                   = 1011&
                        %ERROR_CANTREAD                   = 1012&
                        %ERROR_CANTWRITE                  = 1013&
                        %ERROR_REGISTRY_RECOVERED         = 1014&
                        %ERROR_REGISTRY_CORRUPT           = 1015&
                        %ERROR_REGISTRY_IO_FAILED         = 1016&
                        %ERROR_NOT_REGISTRY_FILE          = 1017&
                        %ERROR_KEY_DELETED                = 1018&
                        %ERROR_NO_LOG_SPACE               = 1019&
                        %ERROR_KEY_HAS_CHILDREN           = 1020&
                        %ERROR_CHILD_MUST_BE_VOLATILE     = 1021&
                        %ERROR_NOTIFY_ENUM_DIR            = 1022&
                        %ERROR_DEPENDENT_SERVICES_RUNNING = 1051&
                        %ERROR_INVALID_SERVICE_CONTROL    = 1052&
                        %ERROR_SERVICE_REQUEST_TIMEOUT    = 1053&
                        %ERROR_SERVICE_NO_THREAD          = 1054&
                        %ERROR_SERVICE_DATABASE_LOCKED    = 1055&
                        %ERROR_SERVICE_ALREADY_RUNNING    = 1056&
                        %ERROR_INVALID_SERVICE_ACCOUNT    = 1057&
                        %ERROR_SERVICE_DISABLED           = 1058&
                        %ERROR_CIRCULAR_DEPENDENCY        = 1059&
                        %ERROR_SERVICE_DOES_NOT_EXIST     = 1060&
                        %ERROR_SERVICE_CANNOT_ACCEPT_CTRL = 1061&
                        %ERROR_SERVICE_NOT_ACTIVE         = 1062&
                        %ERROR_FAILED_SERVICE_CONTROLLER_CONNECT = 1063&
                        %ERROR_EXCEPTION_IN_SERVICE       = 1064&
                        %ERROR_DATABASE_DOES_NOT_EXIST    = 1065&
                        %ERROR_SERVICE_SPECIFIC_ERROR     = 1066&
                        %ERROR_PROCESS_ABORTED            = 1067&
                        %ERROR_SERVICE_DEPENDENCY_FAIL    = 1068&
                        %ERROR_SERVICE_LOGON_FAILED       = 1069&
                        %ERROR_SERVICE_START_HANG         = 1070&
                        %ERROR_INVALID_SERVICE_LOCK       = 1071&
                        %ERROR_SERVICE_MARKED_FOR_DELETE  = 1072&
                        %ERROR_SERVICE_EXISTS             = 1073&
                        %ERROR_ALREADY_RUNNING_LKG        = 1074&
                        %ERROR_SERVICE_DEPENDENCY_DELETED = 1075&
                        %ERROR_BOOT_ALREADY_ACCEPTED      = 1076&
                        %ERROR_SERVICE_NEVER_STARTED      = 1077&
                        %ERROR_DUPLICATE_SERVICE_NAME     = 1078&
                        %ERROR_DIFFERENT_SERVICE_ACCOUNT  = 1079&
                        %ERROR_CANNOT_DETECT_DRIVER_FAILURE = 1080&
                        %ERROR_CANNOT_DETECT_PROCESS_ABORT = 1081&
                        %ERROR_NO_RECOVERY_PROGRAM        = 1082&
                        %ERROR_SERVICE_NOT_IN_EXE         = 1083&
                        %ERROR_END_OF_MEDIA               = 1100&
                        %ERROR_FILEMARK_DETECTED          = 1101&
                        %ERROR_BEGINNING_OF_MEDIA         = 1102&
                        %ERROR_SETMARK_DETECTED           = 1103&
                        %ERROR_NO_DATA_DETECTED           = 1104&
                        %ERROR_PARTITION_FAILURE          = 1105&
                        %ERROR_INVALID_BLOCK_LENGTH       = 1106&
                        %ERROR_DEVICE_NOT_PARTITIONED     = 1107&
                        %ERROR_UNABLE_TO_LOCK_MEDIA       = 1108&
                        %ERROR_UNABLE_TO_UNLOAD_MEDIA     = 1109&
                        %ERROR_MEDIA_CHANGED              = 1110&
                        %ERROR_BUS_RESET                  = 1111&
                        %ERROR_NO_MEDIA_IN_DRIVE          = 1112&
                        %ERROR_NO_UNICODE_TRANSLATION     = 1113&
                        %ERROR_DLL_INIT_FAILED            = 1114&
                        %ERROR_SHUTDOWN_IN_PROGRESS       = 1115&
                        %ERROR_NO_SHUTDOWN_IN_PROGRESS    = 1116&
                        %ERROR_IO_DEVICE                  = 1117&
                        %ERROR_SERIAL_NO_DEVICE           = 1118&
                        %ERROR_IRQ_BUSY                   = 1119&
                        %ERROR_MORE_WRITES                = 1120&
                        %ERROR_COUNTER_TIMEOUT            = 1121&
                        %ERROR_FLOPPY_ID_MARK_NOT_FOUND   = 1122&
                        %ERROR_FLOPPY_WRONG_CYLINDER      = 1123&
                        %ERROR_FLOPPY_UNKNOWN_ERROR       = 1124&
                        %ERROR_FLOPPY_BAD_REGISTERS       = 1125&
                        %ERROR_DISK_RECALIBRATE_FAILED    = 1126&
                        %ERROR_DISK_OPERATION_FAILED      = 1127&
                        %ERROR_DISK_RESET_FAILED          = 1128&
                        %ERROR_EOM_OVERFLOW               = 1129&
                        %ERROR_NOT_ENOUGH_SERVER_MEMORY   = 1130&
                        %ERROR_POSSIBLE_DEADLOCK          = 1131&
                        %ERROR_MAPPED_ALIGNMENT           = 1132&
                        %ERROR_SET_POWER_STATE_VETOED     = 1140&
                        %ERROR_SET_POWER_STATE_FAILED     = 1141&
                        %ERROR_TOO_MANY_LINKS             = 1142&
                        %ERROR_OLD_WIN_VERSION            = 1150&
                        %ERROR_APP_WRONG_OS               = 1151&
                        %ERROR_SINGLE_INSTANCE_APP        = 1152&
                        %ERROR_RMODE_APP                  = 1153&
                        %ERROR_INVALID_DLL                = 1154&
                        %ERROR_NO_ASSOCIATION             = 1155&
                        %ERROR_DDE_FAIL                   = 1156&
                        %ERROR_DLL_NOT_FOUND              = 1157&
                        %ERROR_NO_MORE_USER_HANDLES       = 1158&
                        %ERROR_MESSAGE_SYNC_ONLY          = 1159&
                        %ERROR_SOURCE_ELEMENT_EMPTY       = 1160&
                        %ERROR_DESTINATION_ELEMENT_FULL   = 1161&
                        %ERROR_ILLEGAL_ELEMENT_ADDRESS    = 1162&
                        %ERROR_MAGAZINE_NOT_PRESENT       = 1163&
                        %ERROR_DEVICE_REINITIALIZATION_NEEDED = 1164&     ' dderror
                        %ERROR_DEVICE_REQUIRES_CLEANING   = 1165&
                        %ERROR_DEVICE_DOOR_OPEN           = 1166&
                        %ERROR_DEVICE_NOT_CONNECTED       = 1167&
                        %ERROR_NOT_FOUND                  = 1168&
                        %ERROR_NO_MATCH                   = 1169&
                        %ERROR_SET_NOT_FOUND              = 1170&
                        %ERROR_POINT_NOT_FOUND            = 1171&
                        %ERROR_NO_TRACKING_SERVICE        = 1172&
                        %ERROR_NO_VOLUME_ID               = 1173&
                        %ERROR_INVALID_VLM_OPERATION      = 1174&
                        %ERROR_UNABLE_TO_REMOVE_REPLACED  = 1175&
                        %ERROR_UNABLE_TO_MOVE_REPLACEMENT = 1176&
                        %ERROR_UNABLE_TO_MOVE_REPLACEMENT_2 = 1177&
                        %ERROR_JOURNAL_DELETE_IN_PROGRESS = 1178&
                        %ERROR_JOURNAL_NOT_ACTIVE         = 1179&
                        %ERROR_POTENTIAL_FILE_FOUND       = 1180&
                        %ERROR_JOURNAL_ENTRY_DELETED      = 1181&
                        %ERROR_CANCELLED                  = 1223&
                        %ERROR_USER_MAPPED_FILE           = 1224&
                        %ERROR_CONNECTION_REFUSED         = 1225&
                        %ERROR_GRACEFUL_DISCONNECT        = 1226&
                        %ERROR_ADDRESS_ALREADY_ASSOCIATED = 1227&
                        %ERROR_ADDRESS_NOT_ASSOCIATED     = 1228&
                        %ERROR_CONNECTION_INVALID         = 1229&
                        %ERROR_CONNECTION_ACTIVE          = 1230&
                        %ERROR_NETWORK_UNREACHABLE        = 1231&
                        %ERROR_HOST_UNREACHABLE           = 1232&
                        %ERROR_PROTOCOL_UNREACHABLE       = 1233&
                        %ERROR_PORT_UNREACHABLE           = 1234&
                        %ERROR_REQUEST_ABORTED            = 1235&
                        %ERROR_CONNECTION_ABORTED         = 1236&
                        %ERROR_RETRY                      = 1237&
                        %ERROR_CONNECTION_COUNT_LIMIT     = 1238&
                        %ERROR_LOGIN_TIME_RESTRICTION     = 1239&
                        %ERROR_LOGIN_WKSTA_RESTRICTION    = 1240&
                        %ERROR_INCORRECT_ADDRESS          = 1241&
                        %ERROR_ALREADY_REGISTERED         = 1242&
                        %ERROR_SERVICE_NOT_FOUND          = 1243&
                        %ERROR_NOT_AUTHENTICATED          = 1244&
                        %ERROR_NOT_LOGGED_ON              = 1245&
                        %ERROR_CONTINUE                   = 1246&     ' dderror
                        %ERROR_ALREADY_INITIALIZED        = 1247&
                        %ERROR_NO_MORE_DEVICES            = 1248&     ' dderror
                        %ERROR_NO_SUCH_SITE               = 1249&
                        %ERROR_DOMAIN_CONTROLLER_EXISTS   = 1250&
                        %ERROR_ONLY_IF_CONNECTED          = 1251&
                        %ERROR_OVERRIDE_NOCHANGES         = 1252&
                        %ERROR_BAD_USER_PROFILE           = 1253&
                        %ERROR_NOT_SUPPORTED_ON_SBS       = 1254&
                        %ERROR_LICENSE_QUOTA_EXCEEDED     = 1395&
                        %ERROR_WRONG_TARGET_NAME          = 1396&
                        %ERROR_MUTUAL_AUTH_FAILED         = 1397&
                        %ERROR_TIME_SKEW                  = 1398&
                        %ERROR_GLOBAL_ONLY_HOOK           = 1429&
                        %ERROR_NO_SYSTEM_RESOURCES        = 1450&
                        %ERROR_NONPAGED_SYSTEM_RESOURCES  = 1451&
                        %ERROR_PAGED_SYSTEM_RESOURCES     = 1452&
                        %ERROR_WORKING_SET_QUOTA          = 1453&
                        %ERROR_PAGEFILE_QUOTA             = 1454&
                        %ERROR_COMMITMENT_LIMIT           = 1455&
                        %ERROR_MENU_ITEM_NOT_FOUND        = 1456&
                        %ERROR_INVALID_KEYBOARD_HANDLE    = 1457&
                        %ERROR_HOOK_TYPE_NOT_ALLOWED      = 1458&
                        %ERROR_REQUIRES_INTERACTIVE_WINDOWSTATION = 1459&
                        %ERROR_TIMEOUT                    = 1460&
                        %ERROR_INVALID_MONITOR_HANDLE     = 1461&
                        %ERROR_INSTALL_SERVICE_FAILURE    = 1601&
                        %ERROR_INSTALL_USEREXIT           = 1602&
                        %ERROR_INSTALL_FAILURE            = 1603&
                        %ERROR_INSTALL_SUSPEND            = 1604&
                        %ERROR_UNKNOWN_PRODUCT            = 1605&
                        %ERROR_UNKNOWN_FEATURE            = 1606&
                        %ERROR_UNKNOWN_COMPONENT          = 1607&
                        %ERROR_UNKNOWN_PROPERTY           = 1608&
                        %ERROR_INVALID_HANDLE_STATE       = 1609&
                        %ERROR_BAD_CONFIGURATION          = 1610&
                        %ERROR_INDEX_ABSENT               = 1611&
                        %ERROR_INSTALL_SOURCE_ABSENT      = 1612&
                        %ERROR_INSTALL_PACKAGE_VERSION    = 1613&
                        %ERROR_PRODUCT_UNINSTALLED        = 1614&
                        %ERROR_BAD_QUERY_SYNTAX           = 1615&
                        %ERROR_INVALID_FIELD              = 1616&
                        %ERROR_DEVICE_REMOVED             = 1617&
                        %ERROR_INSTALL_ALREADY_RUNNING    = 1618&
                        %ERROR_INSTALL_PACKAGE_OPEN_FAILED = 1619&
                        %ERROR_INSTALL_PACKAGE_INVALID    = 1620&
                        %ERROR_INSTALL_UI_FAILURE         = 1621&
                        %ERROR_INSTALL_LOG_FAILURE        = 1622&
                        %ERROR_INSTALL_LANGUAGE_UNSUPPORTED = 1623&
                        %ERROR_INSTALL_TRANSFORM_FAILURE  = 1624&
                        %ERROR_INSTALL_PACKAGE_REJECTED   = 1625&
                        %ERROR_FUNCTION_NOT_CALLED        = 1626&
                        %ERROR_FUNCTION_FAILED            = 1627&
                        %ERROR_INVALID_TABLE              = 1628&
                        %ERROR_DATATYPE_MISMATCH          = 1629&
                        %ERROR_UNSUPPORTED_TYPE           = 1630&
                        %ERROR_CREATE_FAILED              = 1631&
                        %ERROR_INSTALL_TEMP_UNWRITABLE    = 1632&
                        %ERROR_INSTALL_PLATFORM_UNSUPPORTED = 1633&
                        %ERROR_INSTALL_NOTUSED            = 1634&
                        %ERROR_PATCH_PACKAGE_OPEN_FAILED  = 1635&
                        %ERROR_PATCH_PACKAGE_INVALID      = 1636&
                        %ERROR_PATCH_PACKAGE_UNSUPPORTED  = 1637&
                        %ERROR_PRODUCT_VERSION            = 1638&
                        %ERROR_INVALID_COMMAND_LINE       = 1639&
                        %ERROR_INSTALL_REMOTE_DISALLOWED  = 1640&
                        %ERROR_SUCCESS_REBOOT_INITIATED   = 1641&
                        %ERROR_PATCH_TARGET_NOT_FOUND     = 1642&
                        
                        %ERROR_PATCH_PACKAGE_REJECTED     = 1643&   'added 3 JUL 2019
                        %ERROR_INSTALL_TRANSFORM_REJECTED = 1644&
                        %ERROR_INSTALL_REMOTE_PROHIBITED  = 1645&
                        %ERROR_PATCH_REMOVAL_UNSUPPORTED  = 1646&
                        %ERROR_UNKNOWN_PATCH              = 1647&
                        %ERROR_PATCH_NO_SEQUENCE          = 1648&
                        %ERROR_PATCH_REMOVAL_DISALLOWED   = 1649&
                        %ERROR_INVALID_PATCH_XML          = 1650&
                        %ERROR_PATCH_MANAGED_ADVERTISED_PRODUCT = 1651&
                        %ERROR_INSTALL_SERVICE_SAFEBOOT   = 1652&
                        %ERROR_FAIL_FAST_EXCEPTION        = 1653&
                        
                        '//
                        '//
                        '// Predefined Value Types.
                        '//
                        
                        %REG_NONE                        = 0     ' No value type
                        %REG_SZ                          = 1     ' Unicode nul terminated string
                        %REG_EXPAND_SZ                   = 2     ' Unicode nul terminated string
                        %REG_BINARY                      = 3     ' Free form binary
                        %REG_DWORD                       = 4     ' 32-bit number
                        %REG_DWORD_LITTLE_ENDIAN         = 4     ' 32-bit number (same as MACRO REG_DWORD)
                        %REG_DWORD_BIG_ENDIAN            = 5     ' 32-bit number
                        %REG_LINK                        = 6     ' Symbolic Link (unicode)
                        %REG_MULTI_SZ                    = 7     ' Multiple Unicode strings
                        %REG_RESOURCE_LIST               = 8     ' Resource list in the resource map
                        %REG_FULL_RESOURCE_DESCRIPTOR    = 9     ' Resource list in the hardware description
                        %REG_RESOURCE_REQUIREMENTS_LIST  = 10
                        %REG_QWORD                       = 11    ' 64-bit number
                        %REG_QWORD_LITTLE_ENDIAN         = 11    ' 64-bit number (same as MACRO REG_QWORD)
                        
                        '/* timer device capabilities data structure */
                        ' // Size = 8 bytes
                        TYPE TIMECAPS BYTE
                           wPeriodMin AS DWORD   ' UINT wPeriodMin /* minimum period supported  */
                           wPeriodMax AS DWORD   ' UINT wPeriodMax /* maximum period supported  */
                        END TYPE
                        
                        
                        MACRO ACCESS_MASK = DWORD
                        'typedef ACCESS_MASK REGSAM;
                        MACRO REGSAM = ACCESS_MASK
                        
                        
                        DECLARE FUNCTION SetPriorityClass IMPORT "KERNEL32.DLL" ALIAS "SetPriorityClass" ( _
                           BYVAL hProcess AS DWORD _                            ' __in HANDLE hProcess
                         , BYVAL dwPriorityClass AS DWORD _                     ' __in DWORD dwPriorityClass
                         ) AS LONG                                              ' BOOL
                        
                        DECLARE FUNCTION GetCurrentProcess IMPORT "KERNEL32.DLL" ALIAS "GetCurrentProcess" ( _
                         ) AS DWORD                                             ' HANDLE
                        
                        DECLARE FUNCTION RegOpenKeyExA IMPORT "ADVAPI32.DLL" ALIAS "RegOpenKeyExA" ( _
                           BYVAL hKey AS DWORD _                                ' __in HKEY hKey
                         , BYREF lpSubKey AS ASCIIZ _                           ' __in_opt LPCSTR lpSubKey
                         , BYVAL ulOptions AS DWORD _                           ' __in_opt DWORD ulOptions
                         , BYVAL samDesired AS REGSAM _                         ' __in REGSAM samDesired
                         , BYREF phkResult AS DWORD _                           ' __out PHKEY phkResult
                         ) AS LONG                                              ' LSTATUS
                        
                        DECLARE FUNCTION RegQueryValueExA IMPORT "ADVAPI32.DLL" ALIAS "RegQueryValueExA" ( _
                           BYVAL hKey AS DWORD _                                ' __in HKEY hKey
                         , OPTIONAL BYREF lpValueName AS ASCIIZ _               ' __in_opt LPCSTR lpValueName
                         , OPTIONAL BYVAL lpReserved AS DWORD _                 ' __in LPDWORD lpReserved
                         , OPTIONAL BYREF lpType AS DWORD _                     ' __out_opt LPDWORD lpType
                         , OPTIONAL BYREF lpData AS ANY _                       ' __out_opt LPBYTE lpData
                         , OPTIONAL BYREF lpcbData AS DWORD _                   ' __inout_opt LPDWORD lpcbData
                         ) AS LONG                                              ' LSTATUS
                        
                        DECLARE FUNCTION RegCloseKey IMPORT "ADVAPI32.DLL" ALIAS "RegCloseKey" ( _
                           BYVAL hKey AS DWORD _                                ' __in HKEY hKey
                         ) AS LONG                                              ' LSTATUS
                        
                        DECLARE FUNCTION timeGetDevCaps IMPORT "WINMM.DLL" ALIAS "timeGetDevCaps" ( _
                           BYREF ptc AS TIMECAPS _                              ' __out LPTIMECAPS ptc
                         , BYVAL cbtc AS DWORD _                                ' __in UINT cbtc
                         ) AS LONG                                              ' MMRESULT
                        
                        DECLARE FUNCTION timeBeginPeriod IMPORT "WINMM.DLL" ALIAS "timeBeginPeriod" ( _
                           BYVAL uPeriod AS DWORD _                             ' __in UINT uPeriod
                         ) AS LONG                                              ' MMRESULT
                        
                        
                        '//////////////////// End Code Extraction
                        
                        GLOBAL gAction1    AS LONG
                        GLOBAL gAction2    AS LONG
                        GLOBAL g_Result    AS LONG
                        GLOBAL gsX         AS STRING
                        GLOBAL gsY         AS STRING
                        GLOBAL gsZ         AS STRING
                        GLOBAL Test1       AS DOUBLE  'changed 2020-MAR-12
                        GLOBAL Test2       AS DOUBLE  'changed 2020-MAR-12
                        GLOBAL qFreq       AS QUAD
                        GLOBAL giSync      AS LONG
                        GLOBAL giIterate   AS LONG
                        GLOBAL gdA         AS DOUBLE
                        GLOBAL gdB         AS DOUBLE
                        GLOBAL gdC         AS DOUBLE
                        GLOBAL MyBaseFreq  AS DWORD
                        GLOBAL sString     AS STRING
                        
                        FUNCTION PBMAIN AS LONG
                            LOCAL lsOutput        AS STRING
                            LOCAL XC              AS LONG
                            LOCAL NotifyValue     AS LONG
                            LOCAL Variance        AS DOUBLE
                            LOCAL AVG()           AS DOUBLE
                            LOCAL FinalDet        AS DOUBLE 'changed 2020-MAR-12
                            LOCAL SmallTest1      AS DOUBLE
                            LOCAL SmallTest2      AS DOUBLE
                            LOCAL DeltaSmallTest  AS DOUBLE
                        
                            LOCAL Time AS TIMECAPS
                        
                            TimeGetDevCaps( Time, SIZEOF(Time) )
                            timeBeginPeriod(Time.wPeriodMin)
                        
                            DIM AVG(1 TO 10, 1 TO 2)
                        
                            LOCAL sData AS STRING
                            regDataGet(%HKEY_LOCAL_MACHINE, "HARDWARE\DESCRIPTION\System\CentralProcessor\0", "~MHZ", sData)
                        
                            'Mine is 0x00000893 (2195) dword
                            MyBaseFreq = VAL(sData) * 1000000
                        
                            gsX = STRING$(80, "X")   'create the test string
                            gsY = STRING$(80, "Y")   'create the test string
                            gsZ = STRING$(80, "Z")   'create the test string
                            giIterate = 1000         '<-- select your test iterations here (1000 is very speedy and fairly accurate)
                            gdA = 12345678901234567890
                            gdB = 12345678901234567890
                            gdC = 12345678901234567890
                            sString = STRING$(1000, 65) '1000 "A"
                        
                            Variance = 0.0000020 ' changed to .0000020 on 2020-04-06 changed to .0000050 on 2020-03-12
                        
                            SLEEP 2    '<= Good candidate for SLEEP 16
                        
                            IF giIterate < 1000 THEN
                                ? "Sorry, the requested tests could not be run. giIterate is too low for an adequate sample."
                                GOTO CloseDown
                            END IF
                        
                            FOR XC = 1 TO 10  'do 10 runs
                        
                                LOCAL hThread1 AS DWORD
                                THREAD CREATE ProcessTest1(1) TO hThread1
                                THREAD CLOSE hThread1 TO hThread1
                        
                                LOCAL hThread2 AS DWORD
                                THREAD CREATE ProcessTest2(1) TO hThread2
                                THREAD CLOSE hThread2 TO hThread2
                        
                                SLEEP 10    '<= Good candidate for DIALOG DOEVENTS 10
                        
                                giSync = 1
                        
                                DO WHILE gAction1 = 1 OR gAction2 = 1
                                    SLEEP 10
                                LOOP
                                g_Result = SetPriorityClass(GetCurrentProcess(), %NORMAL_PRIORITY_CLASS)
                                AVG(XC, 1) = Test1
                                AVG(XC, 2) = Test2
                        
                            NEXT
                        
                            'find the smallest test values for the 10 samples
                            SmallTest1 = AVG(1,1)
                            SmallTest2 = AVG(1,2)
                        
                            FOR XC = 1 TO 10
                                IF AVG(XC,1) <> 0 AND AVG(XC,1) < SmallTest1 THEN
                                    SmallTest1 = AVG(XC, 1)
                                END IF
                            NEXT XC
                        
                            FOR XC = 1 TO 10
                                IF AVG(XC,2) <> 0 AND AVG(XC,2) < SmallTest2 THEN
                                    SmallTest2 = AVG(XC, 2)
                                END IF
                            NEXT XC
                        
                            SmallTest1 = SmallTest1/MyBaseFreq
                            SmallTest2 = SmallTest2/MyBaseFreq
                            DeltaSmallTest = ABS(SmallTest2 - SmallTest1)
                        
                            lsOutput = _
                                "10 Runs Completed." + $CRLF + _
                                USING$("&##.#######", "Test 1 smallest loop time at " + STR$(giIterate * 10) + " iterations = ", SmallTest1) + $CRLF + _
                                USING$("&##.#######", "Test 2 smallest loop time at " + STR$(giIterate * 10) + " iterations = ", SmallTest2) + $CRLF + $CRLF + _
                                USING$("&##.#######", "The variance is ", DeltaSmallTest) + $CRLF
                        
                            IF DeltaSmallTest <= Variance THEN
                                lsOutput = lsOutput + "Not significant."
                            ELSE
                                lsOutput = lsOutput + "Is significant."
                            END IF
                        
                        
                            'is one of the code samples faster or not?
                            IF SmallTest1 = SmallTest2 THEN
                                NotifyValue = 0
                                FinalDet = 0
                            END IF
                            IF SmallTest1 > SmallTest2 THEN
                                NotifyValue = 1
                                FinalDet = SmallTest1/SmallTest2
                            END IF
                            IF SmallTest1 < SmallTest2 THEN
                                NotifyValue = 2
                                FinalDet = SmallTest2/SmallTest1
                            END IF
                        
                            'determine which message to display
                            SELECT CASE NotifyValue
                                CASE 0
                                    lsOutput = lsOutput + $CRLF + $CRLF + _
                                    "The tests did not show any difference in the code segments."
                                CASE 1
                                    IF ABS(SmallTest1 - SmallTest2) <= Variance THEN
                                        lsOutput = lsOutput + $CRLF + $CRLF + _
                                        "The tests did not show any significant difference in the code segments"
                                        IF SmallTest1 < SmallTest2 THEN
                                            lsOutput = lsOutput + $CRLF + _
                                            "but code segment 1 was slightly faster than code segment 2."
                                        END IF
                                        IF SmallTest2 < SmallTest1 THEN
                                            lsOutput = lsOutput + $CRLF + _
                                            "but code segment 2 was slightly faster than code segment 1."
                                        END IF
                                    ELSE
                                        lsOutput = lsOutput + $CRLF + $CRLF + _
                                        USING$("&##.##", "Code segment 2 is ", FinalDet) + " times faster than code segment 1."
                                    END IF
                                CASE 2
                                    IF ABS(SmallTest1 - SmallTest2) <= Variance THEN
                                        lsOutput = lsOutput + $CRLF + $CRLF + _
                                        "The tests did not show any significant difference in the code segments"
                                        IF SmallTest1 < SmallTest2 THEN
                                            lsOutput = lsOutput + $CRLF + _
                                            "but code segment 1 was slightly faster than code segment 2."
                                        END IF
                                        IF SmallTest2 < SmallTest1 THEN
                                            lsOutput = lsOutput + $CRLF + _
                                            "but code segment 2 was slightly faster than code segment 1."
                                        END IF
                                    ELSE
                                        lsOutput = lsOutput + $CRLF + $CRLF + _
                                        USING$("&##.##", "Code segment 1 is ", FinalDet) + " times faster than code segment 2."
                                    END IF
                        
                            END SELECT
                        
                            ? lsOutput, 0, $appName
                        
                            CloseDown:
                        END FUNCTION
                        
                        'Thanks to Pierre Bellisle
                        FUNCTION regDataGet(hMainKey AS DWORD, sKeyName AS STRING, sValueName AS STRING, sData AS STRING) AS LONG
                         LOCAL Retval    AS LONG
                         LOCAL dwSize    AS DWORD
                         LOCAL hKey      AS DWORD
                         LOCAL dwRegType AS DWORD
                        
                         sData = ""
                         IF RegOpenKeyExA(hMainKey, BYVAL STRPTR(sKeyName), BYVAL %NULL, %KEY_READ, hKey) = %ERROR_SUCCESS THEN
                           Retval = RegQueryValueExA(hKey, BYVAL STRPTR(sValueName), BYVAL %NULL, _
                                                    BYVAL %NULL, BYVAL %NULL, dwSize)
                           IF Retval = %ERROR_SUCCESS THEN
                             sData = NUL$(dwSize)
                             Retval = RegQueryValueExA(hKey, BYVAL STRPTR(sValueName), BYVAL %NULL, _
                                                      dwRegType, BYVAL STRPTR(sData), dwSize)
                             SELECT CASE dwRegType
                               CASE %REG_SZ, %REG_EXPAND_SZ, %REG_MULTI_SZ
                                 sData = RTRIM$(sData, $NUL) 'Remove one or two ending $NUL
                               CASE %REG_DWORD
                                 sData = FORMAT$(CVDWD(sData)) 'Convert dword to string
                               CASE %REG_QWORD, %REG_QWORD_LITTLE_ENDIAN
                                 sData = FORMAT$(CVQ(sData)) 'Convert quad to string
                             END SELECT
                           END IF
                           RegCloseKey(hKey)
                         END IF
                         FUNCTION = Retval
                        
                        END FUNCTION
                        
                        
                        THREAD FUNCTION ProcessTest1(BYVAL yyy AS LONG) AS LONG
                        
                            gAction1 = 1
                        
                            CheckAgain:
                            IF giSync = 1 THEN
                        
                                CALL DoExternalProcess1
                        
                                gAction1 = 0
                                EXIT FUNCTION
                            END IF
                            GOTO CheckAgain
                            EXIT FUNCTION
                        
                        END FUNCTION
                        
                        THREAD FUNCTION ProcessTest2(BYVAL yyy AS LONG) AS LONG
                        
                            gAction2 = 1
                        
                            CheckAgain:
                            IF giSync = 1 THEN
                        
                                CALL DoExternalProcess2
                        
                                gAction2 = 0
                                EXIT FUNCTION
                            END IF
                            GOTO CheckAgain
                            EXIT FUNCTION
                        
                        END FUNCTION
                        
                        FUNCTION DoExternalProcess1() AS LONG
                            LOCAL XA    AS LONG
                            LOCAL lsA   AS STRING
                            LOCAL XD    AS LONG
                            LOCAL Done  AS QUAD
                            LOCAL Start AS QUAD
                            LOCAL AA    AS QUAD
                            LOCAL Index   AS DWORD
                            LOCAL RetVal  AS DWORD
                            LOCAL a, b, c AS QUAD '64-BIT, long 32-bit, INTEGER 16-bit, BYTE 8-bit
                        
                            a = 1010101010101010101010101010101010101010101010101010101010101010
                            b = 0
                            c = 1111111111111111111111111111111111111111111111111111111111111111
                        
                            g_Result = SetPriorityClass(GetCurrentProcess(), %REALTIME_PRIORITY_CLASS)
                        
                            TIX Start
                            FOR XA = 1 TO giIterate
                                'Put your code here
                                FOR XD = 1 TO 10000
                                    b = a
                                    a = c
                                    c = b
                        
                                NEXT XD
                        
                                'FOR index = 0 TO 500     '<=reduce to make testing quicker
                                '  ByRefStringTry(sString, sString, sString, sString)
                                'NEXT
                                'FOR index = 0 TO 50000
                                '  RetVal = ByRefDwordTry(index, index, index, index)
                                'NEXT
                        
                                'lsA = lsA + gsX + gsY + gsZ + $CRLF  '(for sample test)
                        
                                'FOR XD = 1 TO 50
                                '    AA = AA + (gdA * gdB * gdC)/5555
                                'NEXT XD
                            NEXT
                            TIX Done
                            Test1 = (Done - Start)/giIterate
                        END FUNCTION
                        
                        FUNCTION DoExternalProcess2() AS LONG
                            LOCAL XA    AS LONG
                            LOCAL lsA   AS STRING
                            LOCAL XD    AS LONG
                            LOCAL Done  AS QUAD
                            LOCAL Start AS QUAD
                            LOCAL AA    AS QUAD
                            LOCAL Index   AS DWORD
                            LOCAL RetVal  AS DWORD
                            LOCAL a, b, c AS QUAD '64-BIT, long 32-bit, INTEGER 16-bit, BYTE 8-bit
                        
                            a = 1010101010101010101010101010101010101010101010101010101010101010
                            b = 0
                            c = 1111111111111111111111111111111111111111111111111111111111111111
                        
                            g_Result = SetPriorityClass(GetCurrentProcess(), %REALTIME_PRIORITY_CLASS)
                        
                            TIX Start
                            FOR XA = 1 TO giIterate
                                'Put your code here
                                FOR XD = 1 TO 10000
                                    'SWAP a, c
                                    ! movsd xmm0, a
                                    ! movsd xmm1, c
                        
                                  ' -----------------------------------
                                    ! movsd xmm2, xmm0
                                    ! movsd xmm0, xmm1      ' swap code
                                    ! movsd xmm1, xmm2
                                  ' -----------------------------------
                        
                                    ! movsd a, xmm0
                                    ! movsd c, xmm1
                                NEXT XD
                        
                                'FOR index = 0 TO 500     '<=reduce to make testing quicker
                                '  ByValStringTry(sString, sString, sString, sString)
                                'NEXT
                                'FOR index = 0 TO 50000
                                '  RetVal = ByValDwordTry(index, index, index, index)
                                'NEXT
                        
                                'lsA = lsA + gsX + gsY + gsZ + $CRLF  'same as test 1 loops  (for sample test)
                        
                                'lsA = BUILD$(lsA, gsX, gsY, gsZ, $CRLF) '(for comparison test)
                                'NOTE: With BUILD$ "Generally speaking, the greater the number of parameters,
                                'the greater the increase in execution speed." Bob Zale
                                'Build or concatenate strings with very high efficiency.
                        
                                'FOR XD = 1 TO 50   'same as test 1 loops  (for sample test)
                                '    AA = AA + (gdA * gdB * gdC)/5555
                                'NEXT XD
                        
                                'FOR XD = 1 TO 10000 '200 times the loops in test 1 (for comparison test)
                                '    AA = AA + (gdA * gdB * gdC)/5555
                                'NEXT XD
                        
                            NEXT
                        
                            TIX Done
                            Test2 = (Done - Start)/giIterate
                        
                        END FUNCTION
                        
                        '_____________________________________________________________________________
                        
                        FUNCTION ByRefDwordTry(BYREF index1 AS DWORD, BYREF index2 AS DWORD, BYREF index3 AS DWORD, BYREF index4 AS DWORD) AS DWORD
                        END FUNCTION
                        '_____________________________________________________________________________
                        
                        FUNCTION ByValDwordTry(BYVAL index1 AS DWORD, BYVAL index2 AS DWORD, BYVAL index3 AS DWORD, BYVAL index4 AS DWORD) AS DWORD
                        END FUNCTION
                        '_____________________________________________________________________________
                        
                        FUNCTION ByRefStringTry(BYREF s1 AS STRING, BYREF s2 AS STRING, BYREF s3 AS STRING, BYREF s4 AS STRING) AS STRING
                        END FUNCTION
                        '_____________________________________________________________________________
                        
                        FUNCTION ByValStringTry(BYVAL s1 AS STRING, BYVAL s2 AS STRING, BYVAL s3 AS STRING, BYVAL s4 AS STRING) AS STRING
                        END FUNCTION
                        '_____________________________________________________________________________
                        '
                        Last edited by Jim Fritts; 30 Jun 2020, 05:16 PM.

                        Comment

                        Working...
                        X