Home AMX User Forum AMXForums Archive Threads Tips and Tricks

Optimize your code. (Tips and techniques)

This thread is dedicated to known ways to speed up your code execution, reduce memory usage, or make code easier to reuse. This thread should not be used to debate techniques (create a separate thread to handle this). If possible, post proof of speed increase or reduced memory usage.

############################
# Reduce Memory Consumption #
############################

Tip - When using multiple ports on a virtual device, use sequential ports starting at port 1.

Proof - Tech support says so :) The processor allocates memory sequentially for ports. Even if you only use port 1 and port 100, the processor allocates memory to track all ports between 1 and 100 in addition to ports 1 and 100.




##########################
# Faster Loop Execution #
##########################

Tip - When using a For loop, reduce the work being done in the evaluation portion of the for loop. The most efficient for loop I have found counts down, not up.

Example - for(x=MaxNum;x;x--)

Proof -
Line     13 (16:16:47):: START...FOR (nLoop = 1; nLoop <= LENGTH_ARRAY(nInfo); nLoop++)
Line     14 (16:16:51):: ...END
Line     15 (16:16:51):: pass 1: 3876ms
Line     16 (16:17:07):: START...FOR (nLoop = 1; nLoop <= MAX_LENGTH_ARRAY(nInfo); nLoop++)
Line     17 (16:17:11):: ...END
Line     18 (16:17:11):: pass 2: 3694ms
Line     19 (16:17:27):: START...FOR (nLoop = 1, nMax = MAX_LENGTH_ARRAY(nInfo); nLoop <= nMax; nLoop++)
Line     20 (16:17:30):: ...END
Line     21 (16:17:30):: pass 3: 2019ms
Line     22 (16:17:48):: START...FOR (nLoop = MAX_LENGTH_ARRAY(nInfo); nLoop > 0; nLoop--)
Line     23 (16:17:50):: ...END
Line     24 (16:17:50):: pass 4: 1855ms
Line     25 (16:18:08):: START...FOR (nLoop = MAX_LENGTH_ARRAY(nInfo); nLoop; nLoop--)
Line     26 (16:18:10):: ...END
Line     27 (16:18:10):: pass 5: 1557ms




##########################
# Faster Loop Execution #
##########################

Tip - Use stack_vars as counters in for loops.

Proof -
Line     13 (16:16:47):: START...FOR (nLoop = 1; nLoop <= LENGTH_ARRAY(nInfo); nLoop++)
Line     14 (16:16:51):: ...END
Line     15 (16:16:51):: pass 1: 3876ms

This is the same format as pass 1, but with a stack_var.
Line     23 (16:28:35):: START...FOR (snLoop = 1; snLoop <= LENGTH_ARRAY(nInfo); snLoop++)
Line     24 (16:28:39):: ...END
Line     25 (16:28:39):: pass 0: 3478ms$0D$0A



Line     25 (16:18:08):: START...FOR (nLoop = MAX_LENGTH_ARRAY(nInfo); nLoop; nLoop--)
Line     26 (16:18:10):: ...END
Line     27 (16:18:10):: pass 5: 1557ms

This is the same format as pass 5, but with a stack_var used for the counter
Line     28 (16:18:28):: START...FOR (snLoop = MAX_LENGTH_ARRAY(nInfo); snLoop; snLoop--)
Line     29 (16:18:29):: ...END
Line     30 (16:18:29):: pass 6: 1213ms


These are the few that come to mind right now. I look forward to hearing about other optimizations out there.

Jeff
«1345

Comments

  • Jeff,
    This is a very interesting topic. I have been doing this for about ten years now and I never even thought about the difference between using an increasing or decreasing value "for loop". It makes total sense though.

    Out of curiosity how do you calculate the speed of the program? I have some ideas on how to do it but I have never attempted it so I thought why re-invent the wheel. I'll just ask you.
  • Thomas HayesThomas Hayes Posts: 1,164
    Good topic Jeff, I've been working on updating my code now for a few months and wow, I can't believe some of the code I wrote 10, even 5 years ago even worked.
  • Spire_JeffSpire_Jeff Posts: 1,917
    This topic is the child of me reworking some code and speed/memory use is now my focus. (code works, but takes 25 minutes on reboot :) ) I figured that since I am massaging the code, I might as well make some simple changes that won't change the functionality, only the speed in which it happens. I am also consolidating ports and renumbering devices to fit a standard I have created.

    As for the timing, I have two methods I have used. The method listed above is done by parsing strings and calculating time based on when the string arrives. This was written by someone else (unknown to me), but it was what I had around. I have also done testing using a timeline. I start the timeline just before executing the code, then pause it right after the code finishes. I then use the timeline time to decide how long things took. I'm am not sure which is more accurate, but I believe that in either case, you are only talking a couple of ms room for error. I would love to know for sure, but I figure as long as I use the same method for all variations being tested, the overhead involved should be irrelevant in the final comparison.

    One thing becomes clear tho, the processor is very fast. I like to make things happen a LOT (loops over 50000 times) so that most of the tests take at least 1 second (give or take a little). This helps to magnify the actual difference. Right now, the test is the only code running on the processor, but in the future I might start injecting the test code into a work code chunk to see if there is a difference in speed.

    Jeff
  • viningvining Posts: 4,368
    Spire_Jeff wrote:
    Tip - When using multiple ports on a virtual device, use sequential ports starting at port 1.
    Doesn't that apply to non virtual devices also?
  • Spire_JeffSpire_Jeff Posts: 1,917
    vining wrote: »
    Doesn't that apply to non virtual devices also?

    Well, I don't think you have a choice on non-virtual devices. If you need to use port 17 on an NI-3100, you have to use it. I am not aware of any way to remap the physical device.


    I also updated the for loop tests and added benchmark test code to a separate thread in Tips and Tricks.

    #########################
    # Squeeze EVERY last bit out of the processor
    #########################

    tip - If you need to make every single processor cycle count, use ON[variable] and OFF[variable] instead of variable=TRUE and variable=FALSE.

    Proof - see the other post as the information is there. Over 70,000 cycles, ON and OFF were 95ms faster.





    P.S.
    Anyone know of any other competing code bits that would be fun to test?
  • alexanboalexanbo Posts: 282
    How about adding to the on off test, setting the variable to 1 and 0 instead of true and false?
  • Spire_JeffSpire_Jeff Posts: 1,917
    alexanbo wrote: »
    How about adding to the on off test, setting the variable to 1 and 0 instead of true and false?

    Believe it or not, 1 and 0 are slower than TRUE and FALSE!
    Line    122 (19:05:53):: *********************************************************
    Line    123 (19:05:53):: * TEST 8 REPORT: ON[nInfo[nLoop]] .. OFF[nInfo[nLoop]]
    Line    124 (19:05:53):: * Most recent 5 runs:
    Line    125 (19:05:53):: * 1: 1903ms
    Line    126 (19:05:53):: * 2: 1903ms
    Line    127 (19:05:53):: * 3: 1904ms
    Line    128 (19:05:53):: * 4: 1904ms
    Line    129 (19:05:53):: * 5: 1902ms
    Line    130 (19:05:53):: *----------------------------------------------------------
    Line    131 (19:05:53):: * Average run time: 1902ms - over 5 tests
    Line    132 (19:05:53):: *********************************************************
    Line    133 (19:05:53):: *********************************************************
    Line    134 (19:05:53):: * TEST 9 REPORT: nInfo[nLoop]=TRUE .. nInfo[nLoop]=FALSE
    Line    135 (19:05:53):: * Most recent 5 runs:
    Line    136 (19:05:53):: * 1: 1999ms
    Line    137 (19:05:53):: * 2: 1998ms
    Line    138 (19:05:53):: * 3: 1997ms
    Line    139 (19:05:53):: * 4: 1996ms
    Line    140 (19:05:53):: * 5: 1998ms
    Line    141 (19:05:53):: *----------------------------------------------------------
    Line    142 (19:05:53):: * Average run time: 1996ms - over 5 tests
    Line    143 (19:05:53):: *********************************************************
    Line    144 (19:05:53):: *********************************************************
    Line    145 (19:05:53):: * TEST 10 REPORT: nInfo[nLoop]=1 .. nInfo[nLoop]=0
    Line    146 (19:05:53):: * Most recent 5 runs:
    Line    147 (19:05:53):: * 1: 2024ms
    Line    148 (19:05:53):: * 2: 2024ms
    Line    149 (19:05:53):: * 3: 2024ms
    Line    150 (19:05:53):: * 4: 2025ms
    Line    151 (19:05:53):: * 5: 2024ms
    Line    152 (19:05:53):: *----------------------------------------------------------
    Line    153 (19:05:53):: * Average run time: 2024ms - over 5 tests
    Line    154 (19:05:53):: *********************************************************
    

    Jeff
  • Joe HebertJoe Hebert Posts: 2,159
    Up, down, or sideways
    Spire_Jeff wrote:
    The most efficient for loop I have found counts down, not up.
    I did some testing myself and didn?t find that to be the case at all. The time it takes to count up or down in a FOR loop is nearly absolutely identical at least using the method I tried.

    I was looking at your benchmark code in the other thread and I think the testing method may be introducing too much error into the equation and giving you inaccurate conclusions. Why do all the pausing, killing, and creating of TIMELINEs when a simple GET_TIMER should suffice?

    Here is my FOR loop counting code with results. It?s just a FOR loop that counts to 1 million and that?s it aside from the GET_TIMER and SEND_STRING 0 statements. I tested both up and down 10 times and each loop takes about 13 seconds to complete so it should be a plenty big enough sampling size.
    DEFINE_DEVICE
    
    dvTP		= 10001:1:0
    
    DEFINE_EVENT
    
    BUTTON_EVENT[dvTP,1] {
    
       PUSH: {
          
          LONG x
          LONG start
          LONG finish
          
          start = GET_TIMER
          SEND_STRING 0,"'Counting up - timer start = ',ITOA(start)"
          FOR (x=1; x<=1000000; x++) { }
          finish = GET_TIMER
          SEND_STRING 0,"'Counting up - timer end = ',ITOA(finish)"
          SEND_STRING 0,"'Counting up  - total time = ',ITOA(finish-start)"
          
       }
    
    }
    
    BUTTON_EVENT[dvTP,2] {
    
       PUSH: {
       
          LONG x
          LONG start
          LONG finish
          
          start = GET_TIMER
          SEND_STRING 0,"'Counting down - timer start = ',ITOA(start)"
          FOR (x=1000000; x>0; x--) { }
          finish = GET_TIMER
          SEND_STRING 0,"'Counting down - timer forward end = ',ITOA(finish)"
          SEND_STRING 0,"'Counting down - total time = ',ITOA(finish-start)"
          
       }
    
    }
    

    Here are the results for counting up.
    Line      1 :: Counting up - timer start = 3714 - 17:30:45
    Line      2 :: Counting up - timer end = 3846 - 17:30:58
    Line      3 :: [b]Counting up  - total time = 132[/b] - 17:30:58
    Line      4 :: Counting up - timer start = 3866 - 17:31:00
    Line      5 :: Counting up - timer end = 3997 - 17:31:13
    Line      6 :: [b]Counting up  - total time = 131[/b] - 17:31:13
    Line      7 :: Counting up - timer start = 4010 - 17:31:14
    Line      8 :: Counting up - timer end = 4142 - 17:31:28
    Line      9 :: [b]Counting up  - total time = 132[/b] - 17:31:28
    Line     10 :: Counting up - timer start = 4159 - 17:31:29
    Line     11 :: Counting up - timer end = 4291 - 17:31:42
    Line     12 :: [b]Counting up  - total time = 132[/b] - 17:31:42
    Line     13 :: Counting up - timer start = 4309 - 17:31:44
    Line     14 :: Counting up - timer end = 4441 - 17:31:57
    Line     15 :: [b]Counting up  - total time = 132[/b] - 17:31:57
    Line     16 :: Counting up - timer start = 4459 - 17:31:59
    Line     17 :: Counting up - timer end = 4591 - 17:32:13
    Line     18 :: [b]Counting up  - total time = 132[/b] - 17:32:13
    Line     19 :: Counting up - timer start = 4710 - 17:32:24
    Line     20 :: Counting up - timer end = 4842 - 17:32:38
    Line     21 :: [b]Counting up  - total time = 132[/b] - 17:32:38
    Line     22 :: Counting up - timer start = 4873 - 17:32:41
    Line     23 :: Counting up - timer end = 5004 - 17:32:54
    Line     24 :: [b]Counting up  - total time = 131[/b] - 17:32:54
    Line     25 :: Counting up - timer start = 5047 - 17:32:58
    Line     26 :: Counting up - timer end = 5179 - 17:33:11
    Line     27 :: [b]Counting up  - total time = 132[/b] - 17:33:11
    Line     28 :: Counting up - timer start = 5198 - 17:33:13
    Line     29 :: Counting up - timer end = 5330 - 17:33:27
    Line     30 :: [b]Counting up  - total time = 132[/b] - 17:33:27
    

    And here are for all practical purposes identical results for counting down.
    Line     31 :: Counting down - timer start = 5368 - 17:33:30
    Line     32 :: Counting down - timer forward end = 5499 - 17:33:44
    Line     33 :: [b]Counting down - total time = 131[/b] - 17:33:44
    Line     34 :: Counting down - timer start = 5517 - 17:33:45
    Line     35 :: Counting down - timer forward end = 5648 - 17:33:59
    Line     36 :: [b]Counting down - total time = 131[/b] - 17:33:59
    Line     37 :: Counting down - timer start = 5671 - 17:34:01
    Line     38 :: Counting down - timer forward end = 5803 - 17:34:14
    Line     39 :: [b]Counting down - total time = 132[/b] - 17:34:14
    Line     40 :: Counting down - timer start = 5826 - 17:34:16
    Line     41 :: Counting down - timer forward end = 5958 - 17:34:29
    Line     42 :: [b]Counting down - total time = 132[/b] - 17:34:29
    Line     43 :: Counting down - timer start = 6014 - 17:34:35
    Line     44 :: Counting down - timer forward end = 6146 - 17:34:48
    Line     45 :: [b]Counting down - total time = 132[/b] - 17:34:48
    Line     46 :: Counting down - timer start = 6163 - 17:34:50
    Line     47 :: Counting down - timer forward end = 6294 - 17:35:03
    Line     48 :: [b]Counting down - total time = 131[/b] - 17:35:03
    Line     49 :: Counting down - timer start = 6306 - 17:35:04
    Line     50 :: Counting down - timer forward end = 6438 - 17:35:18
    Line     51 :: [b]Counting down - total time = 132[/b] - 17:35:18
    Line     52 :: Counting down - timer start = 6507 - 17:35:25
    Line     53 :: Counting down - timer forward end = 6639 - 17:35:38
    Line     54 :: [b]Counting down - total time = 132[/b] - 17:35:38
    Line     55 :: Counting down - timer start = 6651 - 17:35:39
    Line     56 :: Counting down - timer forward end = 6782 - 17:35:52
    Line     57 :: [b]Counting down - total time = 131[/b] - 17:35:52
    Line     58 :: Counting down - timer start = 6794 - 17:35:53
    Line     59 :: Counting down - timer forward end = 6926 - 17:36:06
    Line     60 :: [b]Counting down - total time = 132[/b] - 17:36:06
    
  • viningvining Posts: 4,368
    Spire_Jeff wrote:
    Well, I don't think you have a choice on non-virtual devices. If you need to use port 17 on an NI-3100, you have to use it. I am not aware of any way to remap the physical device.
    Actually I was thinking more in the lines of real TP device ports vs virtual TP ports. It might just be the way I personally think but when I think of a virtual device port and their resources and how I use them I think of them more as a virtual TP port not so much as a virtual NI device port. It might just be that the way I think is slightly abnormal.

    However if your physical NI port aren't defined the same should hold true, they won't take up resources so use those ports sequentially as well and not use serial ports 1 & 7 leaving 2-6 un-used for example.
  • Spire_JeffSpire_Jeff Posts: 1,917
    Joe Hebert wrote: »
    I did some testing myself and didn?t find that to be the case at all. The time it takes to count up or down in a FOR loop is nearly absolutely identical at least using the method I tried.

    Look closer at the for loops :) The way to make counting down faster is to reduce the operations. Try the following:
    for(x=Max;x;x--){}
    

    Notice how the comparison is just x, not x>0. That is where I think the gain comes from.


    Joe Hebert wrote: »
    I was looking at your benchmark code in the other thread and I think the testing method may be introducing too much error into the equation and giving you inaccurate conclusions. Why do all the pausing, killing, and creating of TIMELINEs when a simple GET_TIMER should suffice?


    I could probably change the timeline aspect, but that was my original thought on the task. I may have been trying something else at the time, but that's the way it was so I just kept it. It shouldn't make a difference as long as the overhead is the same from test to test, but if I get a moment, I might try modifying the code to use your suggestion.

    Jeff
  • Spire_JeffSpire_Jeff Posts: 1,917
    vining wrote: »
    Actually I was thinking more in the lines of real TP device ports vs virtual TP ports. It might just be the way I personally think but when I think of a virtual device port and their resources and how I use them I think of them more as a virtual TP port not so much as a virtual NI device port. It might just be that the way I think is slightly abnormal.

    However if your physical NI port aren't defined the same should hold true, they won't take up resources so use those ports sequentially as well and not use serial ports 1 & 7 leaving 2-6 un-used for example.

    I see where you are coming from now. Yes, the same holds true for touch panels. While we are mentioning touch panels and ports, I just recalled another thing... I believe that the set_virtual_channel_count() command is done in blocks of 255 or was it 256. I will have to try to find the original post or the documentation to verify this. I guess the general rule of thumb is to start at the lowest number (generally 1) and try to go up sequentially in everything AMX.

    The only exception that I have found is in actual device numbers. If it's not defined, it won't be tracked.

    Jeff
  • Joe HebertJoe Hebert Posts: 2,159
    Spire_Jeff wrote: »
    Look closer at the for loops :) The way to make counting down faster is to reduce the operations. Try the following:
    for(x=Max;x;x--){}
    

    Notice how the comparison is just x, not x>0. That is where I think the gain comes from.
    Well if you're not going to compare apples to apples what fun are you? :)

    A FOR loop that counts down is still not faster but I do agree that the comparison of x vs. x>0 is faster which is good to know.
  • Joe HebertJoe Hebert Posts: 2,159
    Spire_Jeff wrote:
    Believe it or not, 1 and 0 are slower than TRUE and FALSE!
    Sorry, I don?t believe it and I sure wouldn?t expect them to be different. I tested 1 and 0 and then TRUE and FALSE one million times in a FOR loop and saw no difference. The results are below.
    Spire_Jeff wrote:
    If you need to make every single processor cycle count, use ON[variable] and OFF[variable] instead of variable=TRUE and variable=FALSE.
    I got the opposite results. Running through a FOR loop one million times I found that TRUE/FALSE (1/0) is faster than ON/OFF by about 5%. The results are below.

    Here is the code ? The FOR loops each take about 20 seconds to run.
    DEFINE_DEVICE
    
    dvTP		= 10001:1:0
    
    DEFINE_VARIABLE
    
    INTEGER nVar
    
    DEFINE_EVENT
    
    BUTTON_EVENT[dvTP,1] {
    
       PUSH: {
          
          LONG x
          LONG start
          LONG finish
          
          start = GET_TIMER
          SEND_STRING 0,"'ON/OFF - timer start = ',ITOA(start)"
          FOR (x=1; x<=1000000; x++) { 
    	 ON[nVar]
    	 OFF[nVar]
          }
          finish = GET_TIMER
          SEND_STRING 0,"'ON/OFF - timer end = ',ITOA(finish)"
          SEND_STRING 0,"'ON/OFF  - total time = ',ITOA(finish-start)"
          
       }
    
    }
    
    BUTTON_EVENT[dvTP,2] {
    
       PUSH: {
          
          LONG x
          LONG start
          LONG finish
          
          start = GET_TIMER
          SEND_STRING 0,"'1/0 - timer start = ',ITOA(start)"
          FOR (x=1; x<=1000000; x++) { 
    	 nVar = 1
    	 nVar = 0
          }
          finish = GET_TIMER
          SEND_STRING 0,"'1/0 - timer end = ',ITOA(finish)"
          SEND_STRING 0,"'1/0  - total time = ',ITOA(finish-start)"
          
       }
    
    }
    
    BUTTON_EVENT[dvTP,3] {
    
       PUSH: {
          
          LONG x
          LONG start
          LONG finish
          
          start = GET_TIMER
          SEND_STRING 0,"'TRUE/FALSE - timer start = ',ITOA(start)"
          FOR (x=1; x<=1000000; x++) { 
    	 nVar = TRUE
    	 nVar = FALSE
          }
          finish = GET_TIMER
          SEND_STRING 0,"'TRUE/FALSE - timer end = ',ITOA(finish)"
          SEND_STRING 0,"'TRUE/FALSE  - total time = ',ITOA(finish-start)"
          
       }
    
    }
    

    And here are the results which show that ON/OFF is slightly slower than TRUE/FALSE (1/0) and that TRUE/FALSE is the same as 1/0.
    Line      1 :: ON/OFF - timer start = 6300 - 20:18:16
    Line      2 :: ON/OFF - timer end = 6516 - 20:18:38
    Line      3 :: [b]ON/OFF  - total time = 216[/b] - 20:18:38
    Line      4 :: ON/OFF - timer start = 6537 - 20:18:40
    Line      5 :: ON/OFF - timer end = 6754 - 20:19:02
    Line      6 :: [b]ON/OFF  - total time = 217[/b] - 20:19:02
    Line      7 :: ON/OFF - timer start = 6776 - 20:19:04
    Line      8 :: ON/OFF - timer end = 6992 - 20:19:26
    Line      9 :: [b]ON/OFF  - total time = 216[/b] - 20:19:26
    Line     10 :: ON/OFF - timer start = 7017 - 20:19:28
    Line     11 :: ON/OFF - timer end = 7234 - 20:19:50
    Line     12 :: [b]ON/OFF  - total time = 217[/b] - 20:19:50
    Line     13 :: ON/OFF - timer start = 7292 - 20:19:56
    Line     14 :: ON/OFF - timer end = 7509 - 20:20:17
    Line     15 :: [b]ON/OFF  - total time = 217[/b] - 20:20:17
    
    Line     16 :: 1/0 - timer start = 7563 - 20:20:23
    Line     17 :: 1/0 - timer end = 7768 - 20:20:43
    Line     18 :: [b]1/0  - total time = 205[/b] - 20:20:43
    Line     19 :: 1/0 - timer start = 7789 - 20:20:45
    Line     20 :: 1/0 - timer end = 7994 - 20:21:06
    Line     21 :: [b]1/0  - total time = 205[/b] - 20:21:06
    Line     22 :: 1/0 - timer start = 8025 - 20:21:09
    Line     23 :: 1/0 - timer end = 8229 - 20:21:30
    Line     24 :: [b]1/0  - total time = 204[/b] - 20:21:30
    Line     25 :: 1/0 - timer start = 8251 - 20:21:32
    Line     26 :: 1/0 - timer end = 8456 - 20:21:52
    Line     27 :: [b]1/0  - total time = 205[/b] - 20:21:52
    Line     28 :: 1/0 - timer start = 8494 - 20:21:56
    Line     29 :: 1/0 - timer end = 8698 - 20:22:17
    Line     30 :: [b]1/0  - total time = 204[/b] - 20:22:17
    
    Line     31 :: TRUE/FALSE - timer start = 8717 - 20:22:18
    Line     32 :: TRUE/FALSE - timer end = 8921 - 20:22:39
    Line     33 :: [b]TRUE/FALSE  - total time = 204[/b] - 20:22:39
    Line     34 :: TRUE/FALSE - timer start = 8937 - 20:22:40
    Line     35 :: TRUE/FALSE - timer end = 9142 - 20:23:01
    Line     36 :: [b]TRUE/FALSE  - total time = 205[/b] - 20:23:01
    Line     37 :: TRUE/FALSE - timer start = 9165 - 20:23:03
    Line     38 :: TRUE/FALSE - timer end = 9370 - 20:23:24
    Line     39 :: [b]TRUE/FALSE  - total time = 205[/b] - 20:23:24
    Line     40 :: TRUE/FALSE - timer start = 9429 - 20:23:30
    Line     41 :: TRUE/FALSE - timer end = 9633 - 20:23:50
    Line     42 :: [b]TRUE/FALSE  - total time = 204[/b] - 20:23:50
    Line     43 :: TRUE/FALSE - timer start = 9657 - 20:23:53
    Line     44 :: TRUE/FALSE - timer end = 9862 - 20:24:13
    Line     45 :: [b]TRUE/FALSE  - total time = 205[/b] - 20:24:13
    
  • Spire_JeffSpire_Jeff Posts: 1,917
    As Eminem would say: I guess it back to the lab again....

    When I get into the office, I will try to mix things up a little and see if I can figure out why the results I am getting are different.

    Jeff
  • Joe HebertJoe Hebert Posts: 2,159
    Spire_Jeff wrote:
    When I get into the office, I will try to mix things up a little and see if I can figure out why the results I am getting are different.
    My guess is that not all timelines are created (or killed or paused) equal. Maybe there should be a test for that.:)

    It?s my opinion that the testing method should be as simple and straight forward as possible so that the testing method itself doesn?t end up skewing the results.
  • jazzwyldjazzwyld Posts: 199
    I really like this post

    I think this post is great, although there has been little consensus, makes me want to do some testing as well.
  • Joe HebertJoe Hebert Posts: 2,159
    Spire_Jeff wrote: »
    I will try to mix things up a little and see if I can figure out why the results I am getting are different.
    Jeff,

    It should be noted that the tests I ran were on an old NI-700 with the latest Duet firmware.
  • yuriyuri Posts: 861
    subscribed, excellent thread!
  • ColzieColzie Posts: 470
    yuri wrote: »
    subscribed, excellent thread!

    Agreed!

    This post is at least 10 characters.
  • viningvining Posts: 4,368
    Spire_Jeff wrote:
    I believe that the set_virtual_channel_count() command is done in blocks of 255 or was it 256.
    Well levels are added in blocks of 8 and it would make sense that channels are added in blocks of 256. Also when defining virtual ports above port 1 you can't always trust the master to add resource for it unless you use set_virtual_port_count since by default virtuals have just one port. I used to think the act of defining a virtual port above 1 would be good enough but now I always set my port counts on virtuals if using more than one port per dev number.
  • Joe HebertJoe Hebert Posts: 2,159
    I?m going to be Internetless this morning so if someone wants to jump in and play the role of jacka.ss please feel free.
  • Sample Code

    Folks,

    Here are some testing modules used in Tech Support for many years. Guy Minervini shared these with me.

    Have Fun!

    -Jamie
  • yuriyuri Posts: 861
    jtrader wrote: »
    Folks,

    Here are some testing modules used in Tech Support for many years. Guy Minervini shared these with me.

    Have Fun!

    -Jamie

    it gets even better! :D some reputation for you :)
  • Spire_JeffSpire_Jeff Posts: 1,917
    Spire_Jeff wrote: »
    Believe it or not, 1 and 0 are slower than TRUE and FALSE!
    Line    122 (19:05:53):: *********************************************************
    Line    123 (19:05:53):: * TEST 8 REPORT: ON[nInfo[nLoop]] .. OFF[nInfo[nLoop]]
    Line    124 (19:05:53):: * Most recent 5 runs:
    Line    125 (19:05:53):: * 1: 1903ms
    Line    126 (19:05:53):: * 2: 1903ms
    Line    127 (19:05:53):: * 3: 1904ms
    Line    128 (19:05:53):: * 4: 1904ms
    Line    129 (19:05:53):: * 5: 1902ms
    Line    130 (19:05:53):: *----------------------------------------------------------
    Line    131 (19:05:53):: * Average run time: 1902ms - over 5 tests
    Line    132 (19:05:53):: *********************************************************
    Line    133 (19:05:53):: *********************************************************
    Line    134 (19:05:53):: * TEST 9 REPORT: nInfo[nLoop]=TRUE .. nInfo[nLoop]=FALSE
    Line    135 (19:05:53):: * Most recent 5 runs:
    Line    136 (19:05:53):: * 1: 1999ms
    Line    137 (19:05:53):: * 2: 1998ms
    Line    138 (19:05:53):: * 3: 1997ms
    Line    139 (19:05:53):: * 4: 1996ms
    Line    140 (19:05:53):: * 5: 1998ms
    Line    141 (19:05:53):: *----------------------------------------------------------
    Line    142 (19:05:53):: * Average run time: 1996ms - over 5 tests
    Line    143 (19:05:53):: *********************************************************
    Line    144 (19:05:53):: *********************************************************
    Line    145 (19:05:53):: * TEST 10 REPORT: nInfo[nLoop]=1 .. nInfo[nLoop]=0
    Line    146 (19:05:53):: * Most recent 5 runs:
    Line    147 (19:05:53):: * 1: 2024ms
    Line    148 (19:05:53):: * 2: 2024ms
    Line    149 (19:05:53):: * 3: 2024ms
    Line    150 (19:05:53):: * 4: 2025ms
    Line    151 (19:05:53):: * 5: 2024ms
    Line    152 (19:05:53):: *----------------------------------------------------------
    Line    153 (19:05:53):: * Average run time: 2024ms - over 5 tests
    Line    154 (19:05:53):: *********************************************************
    

    Jeff

    I switched the ID around to see if that changed anything. Here are the results:
    Line      1 (16:07:51):: *********************************************************
    Line      2 (16:07:51):: * TEST 8 REPORT: nInfo[nLoop]=TRUE .. nInfo[nLoop]=FALSE
    Line      3 (16:07:51):: * Most recent 5 runs:
    Line      4 (16:07:51):: * 1: 1997ms
    Line      5 (16:07:51):: * 2: 1997ms
    Line      6 (16:07:51):: * 3: 1998ms
    Line      7 (16:07:51):: * 4: 1998ms
    Line      8 (16:07:51):: * 5: 1998ms
    Line      9 (16:07:51):: *----------------------------------------------------------
    Line     10 (16:07:51):: * Average run time: 1997ms - over 5 tests
    Line     11 (16:07:51):: *********************************************************
    Line     12 (16:07:51):: *********************************************************
    Line     13 (16:07:51):: * TEST 9 REPORT: nInfo[nLoop]=1 .. nInfo[nLoop]=0
    Line     14 (16:07:51):: * Most recent 5 runs:
    Line     15 (16:07:51):: * 1: 2025ms
    Line     16 (16:07:51):: * 2: 2026ms
    Line     17 (16:07:51):: * 3: 2024ms
    Line     18 (16:07:51):: * 4: 2024ms
    Line     19 (16:07:51):: * 5: 2024ms
    Line     20 (16:07:51):: *----------------------------------------------------------
    Line     21 (16:07:51):: * Average run time: 2024ms - over 5 tests
    Line     22 (16:07:51):: *********************************************************
    Line     23 (16:07:51):: *********************************************************
    Line     24 (16:07:51):: * TEST 10 REPORT: ON[nInfo[nLoop]] .. OFF[nInfo[nLoop]]
    Line     25 (16:07:51):: * Most recent 5 runs:
    Line     26 (16:07:51):: * 1: 1903ms
    Line     27 (16:07:51):: * 2: 1903ms
    Line     28 (16:07:51):: * 3: 1901ms
    Line     29 (16:07:51):: * 4: 1902ms
    Line     30 (16:07:51):: * 5: 1904ms
    Line     31 (16:07:51):: *----------------------------------------------------------
    Line     32 (16:07:51):: * Average run time: 1902ms - over 5 tests
    Line     33 (16:07:51):: *********************************************************
    

    Now, I am not sure what else could be different between the tests, but I am about to try your method. I am running these tests on a newer NI-900 and based on some other benchmarks I have, this NI-900 is running almost as fast as an NI-3100 and about 2.25x faster than an NI-3000.

    Jeff
  • HedbergHedberg Posts: 671
    I don't see how TRUE and FALSE could run any faster than 1 and 0. TRUE and FALSE are constants which have the assigned values 1 and 0. I expect that at compile time TRUE and FALSE are replaced and that the token file is the same as if 1 and 0 had been entered. Don't know that for a fact, but that's my understanding of how constants are handled.
  • Joe HebertJoe Hebert Posts: 2,159
    Hedberg wrote: »
    I don't see how TRUE and FALSE could run any faster than 1 and 0. TRUE and FALSE are constants which have the assigned values 1 and 0. I expect that at compile time TRUE and FALSE are replaced and that the token file is the same as if 1 and 0 had been entered. Don't know that for a fact, but that's my understanding of how constants are handled.
    I agree, that's my understanding also.
  • Spire_JeffSpire_Jeff Posts: 1,917
    Hedberg wrote: »
    I don't see how TRUE and FALSE could run any faster than 1 and 0. TRUE and FALSE are constants which have the assigned values 1 and 0. I expect that at compile time TRUE and FALSE are replaced and that the token file is the same as if 1 and 0 had been entered. Don't know that for a fact, but that's my understanding of how constants are handled.

    That is what I thought, the only thing I can think of is that maybe TRUE and FALSE are treated as boolean instead of integers? Or maybe the compiler is doing some sort of optimization on them.... or maybe my testing is flawed :)

    I just finished playing HVAC guy (had to run a new wire to the roof top unit to hook the new Viewstat... 4 wires is just not enough :( ). I'm going to try to change the test method now.

    Jeff
  • Spire_JeffSpire_Jeff Posts: 1,917
    Ok, here are the results using GET_TIMER:
    Line      1 (18:24:28):: *********************************************************
    Line      2 (18:24:28):: * TEST 8 REPORT: nInfo[nLoop]=TRUE .. nInfo[nLoop]=FALSE
    Line      3 (18:24:28):: * Most recent 5 runs:
    Line      4 (18:24:28):: * 1: 20
    Line      5 (18:24:28):: * 2: 21
    Line      6 (18:24:28):: * 3: 20
    Line      7 (18:24:28):: * 4: 20
    Line      8 (18:24:28):: * 5: 20
    Line      9 (18:24:28):: *----------------------------------------------------------
    Line     10 (18:24:28):: * Average run time: 20ms - over 5 tests
    Line     11 (18:24:28):: *********************************************************
    Line     12 (18:24:28):: *********************************************************
    Line     13 (18:24:28):: * TEST 9 REPORT: nInfo[nLoop]=1 .. nInfo[nLoop]=0
    Line     14 (18:24:28):: * Most recent 5 runs:
    Line     15 (18:24:28):: * 1: 20
    Line     16 (18:24:28):: * 2: 20
    Line     17 (18:24:28):: * 3: 21
    Line     18 (18:24:28):: * 4: 21
    Line     19 (18:24:28):: * 5: 21
    Line     20 (18:24:28):: *----------------------------------------------------------
    Line     21 (18:24:28):: * Average run time: 20ms - over 5 tests
    Line     22 (18:24:28):: *********************************************************
    Line     23 (18:24:28):: *********************************************************
    Line     24 (18:24:28):: * TEST 10 REPORT: ON[nInfo[nLoop]] .. OFF[nInfo[nLoop]]
    Line     25 (18:24:28):: * Most recent 5 runs:
    Line     26 (18:24:28):: * 1: 19
    Line     27 (18:24:28):: * 2: 19
    Line     28 (18:24:28):: * 3: 19
    Line     29 (18:24:28):: * 4: 19
    Line     30 (18:24:28):: * 5: 19
    Line     31 (18:24:28):: *----------------------------------------------------------
    Line     32 (18:24:28):: * Average run time: 19ms - over 5 tests
    Line     33 (18:24:28):: *********************************************************
    

    I think I see the problem and the reason I wound up using timelines. Timelines have a higher resolution than GET_TIMER. GET_TIMER has a resolution of only .1 seconds. Timelines allow for .001 seconds. Here is a sample of both methods head to head:
    Line    193 (18:41:10):: *********************************************************
    Line    194 (18:41:10):: * TEST 8 STARTING: nInfo[nLoop]=TRUE .. nInfo[nLoop]=FALSE
    Line    195 (18:41:10):: *********************************************************
    Line    196 (18:41:10):: *********************************************************
    Line    197 (18:41:10):: * TEST 8 FINISHED: nInfo[nLoop]=TRUE .. nInfo[nLoop]=FALSE
    Line    198 (18:41:10):: * Last run time: 1 - nInfo[nLoop]=TRUE .. nInfo[nLoop]=FALSE
    Line    199 (18:41:10):: * Average run time: 0 - over 5 tests - nInfo[nLoop]=TRUE .. nInfo[nLoop]=FALSE
    Line    200 (18:41:10):: *********************************************************
    Line    201 (18:41:10):: *********************************************************
    Line    202 (18:41:10):: * TEST 9 STARTING: nInfo[nLoop]=TRUE .. nInfo[nLoop]=FALSE
    Line    203 (18:41:10):: *********************************************************
    Line    204 (18:41:10):: *********************************************************
    Line    205 (18:41:10):: * TEST 9 FINISHED: nInfo[nLoop]=TRUE .. nInfo[nLoop]=FALSE
    Line    206 (18:41:10):: * Last run time: 0 - nInfo[nLoop]=TRUE .. nInfo[nLoop]=FALSE
    Line    207 (18:41:10):: * Average run time: 0 - over 5 tests - nInfo[nLoop]=TRUE .. nInfo[nLoop]=FALSE
    Line    208 (18:41:10):: *********************************************************
    Line    209 (18:41:10):: *********************************************************
    Line    210 (18:41:10):: * TEST 10 STARTING: ON[nInfo[nLoop]] .. OFF[nInfo[nLoop]]
    Line    211 (18:41:10):: *********************************************************
    Line    212 (18:41:12):: *********************************************************
    Line    213 (18:41:12):: * TEST 10 FINISHED: ON[nInfo[nLoop]] .. OFF[nInfo[nLoop]]
    Line    214 (18:41:12):: * Last run time: 20 - ON[nInfo[nLoop]] .. OFF[nInfo[nLoop]]
    Line    215 (18:41:12):: * Average run time: 19 - over 5 tests - ON[nInfo[nLoop]] .. OFF[nInfo[nLoop]]
    Line    216 (18:41:12):: *********************************************************
    Line    217 (18:41:12):: *********************************************************
    Line    218 (18:41:12):: * TEST 11 STARTING: nInfo[nLoop]=TRUE .. nInfo[nLoop]=FALSE
    Line    219 (18:41:12):: *********************************************************
    Line    220 (18:41:12):: *********************************************************
    Line    221 (18:41:12):: * TEST 11 FINISHED: nInfo[nLoop]=TRUE .. nInfo[nLoop]=FALSE
    Line    222 (18:41:12):: * Last run time: 29ms - nInfo[nLoop]=TRUE .. nInfo[nLoop]=FALSE
    Line    223 (18:41:12):: * Average run time: 28ms - over 5 tests - nInfo[nLoop]=TRUE .. nInfo[nLoop]=FALSE
    Line    224 (18:41:12):: *********************************************************
    Line    225 (18:41:12):: *********************************************************
    Line    226 (18:41:12):: * TEST 12 STARTING: nInfo[nLoop]=TRUE .. nInfo[nLoop]=FALSE
    Line    227 (18:41:12):: *********************************************************
    Line    228 (18:41:12):: *********************************************************
    Line    229 (18:41:12):: * TEST 12 FINISHED: nInfo[nLoop]=TRUE .. nInfo[nLoop]=FALSE
    Line    230 (18:41:12):: * Last run time: 43ms - nInfo[nLoop]=TRUE .. nInfo[nLoop]=FALSE
    Line    231 (18:41:12):: * Average run time: 43ms - over 5 tests - nInfo[nLoop]=TRUE .. nInfo[nLoop]=FALSE
    Line    232 (18:41:12):: *********************************************************
    Line    233 (18:41:12):: *********************************************************
    Line    234 (18:41:12):: * TEST 13 STARTING: ON[nInfo[nLoop]] .. OFF[nInfo[nLoop]]
    Line    235 (18:41:12):: *********************************************************
    Line    236 (18:41:14):: *********************************************************
    Line    237 (18:41:14):: * TEST 13 FINISHED: ON[nInfo[nLoop]] .. OFF[nInfo[nLoop]]
    Line    238 (18:41:14):: * Last run time: 1920ms - ON[nInfo[nLoop]] .. OFF[nInfo[nLoop]]
    Line    239 (18:41:14):: * Average run time: 1917ms - over 5 tests - ON[nInfo[nLoop]] .. OFF[nInfo[nLoop]]
    Line    240 (18:41:14):: *********************************************************
    

    Tests 8, 9, and 10 are done with GET_TIMER. 11,12, and 13 are done with timelines. Tests 8, 9, 11, and 12 are identical in what they are doing. Tests 8 and 11 are looped 1000 times, tests 9 and 12 are looped 1500 times.

    I will post the code so a second set of eyes can see if I am missing something.

    Jeff

    ADDED:

    Here is another set of results. This time I ran the loops 10000 times for the first set and 12000 for the second set.
    Line    561 (19:15:45):: *********************************************************
    Line    562 (19:15:45):: * TEST 8 REPORT: nInfo[nLoop]=TRUE .. nInfo[nLoop]=FALSE
    Line    563 (19:15:45):: * Most recent 5 runs:
    Line    564 (19:15:45):: * 1: 4
    Line    565 (19:15:45):: * 2: 4
    Line    566 (19:15:45):: * 3: 4
    Line    567 (19:15:45):: * 4: 4
    Line    568 (19:15:45):: * 5: 3
    Line    569 (19:15:45):: *----------------------------------------------------------
    Line    570 (19:15:45):: * Average run time: 3 - over 5 tests
    Line    571 (19:15:45):: *********************************************************
    Line    572 (19:15:45):: *********************************************************
    Line    573 (19:15:45):: * TEST 9 REPORT: nInfo[nLoop]=TRUE .. nInfo[nLoop]=FALSE
    Line    574 (19:15:45):: * Most recent 5 runs:
    Line    575 (19:15:45):: * 1: 4
    Line    576 (19:15:45):: * 2: 4
    Line    577 (19:15:45):: * 3: 5
    Line    578 (19:15:45):: * 4: 5
    Line    579 (19:15:45):: * 5: 5
    Line    580 (19:15:45):: *----------------------------------------------------------
    Line    581 (19:15:45):: * Average run time: 4 - over 5 tests
    Line    582 (19:15:45):: *********************************************************
    Line    594 (19:15:45):: *********************************************************
    Line    595 (19:15:45):: * TEST 11 REPORT: nInfo[nLoop]=TRUE .. nInfo[nLoop]=FALSE
    Line    596 (19:15:45):: * Most recent 5 runs:
    Line    597 (19:15:45):: * 1: 362ms
    Line    598 (19:15:45):: * 2: 363ms
    Line    599 (19:15:45):: * 3: 362ms
    Line    600 (19:15:45):: * 4: 362ms
    Line    601 (19:15:45):: * 5: 363ms
    Line    602 (19:15:45):: *----------------------------------------------------------
    Line    603 (19:15:45):: * Average run time: 362ms - over 5 tests
    Line    604 (19:15:45):: *********************************************************
    Line    605 (19:15:45):: *********************************************************
    Line    606 (19:15:45):: * TEST 12 REPORT: nInfo[nLoop]=TRUE .. nInfo[nLoop]=FALSE
    Line    607 (19:15:45):: * Most recent 5 runs:
    Line    608 (19:15:45):: * 1: 435ms
    Line    609 (19:15:45):: * 2: 434ms
    Line    610 (19:15:45):: * 3: 434ms
    Line    611 (19:15:45):: * 4: 435ms
    Line    612 (19:15:45):: * 5: 435ms
    Line    613 (19:15:45):: *----------------------------------------------------------
    Line    614 (19:15:45):: * Average run time: 434ms - over 5 tests
    Line    615 (19:15:45):: *********************************************************
    
  • Spire_JeffSpire_Jeff Posts: 1,917
    Ok, here is the code I am running for the tests. Take a look and let me know if I am overlooking something very obvious. Keep in mind, the report function has not been changed to distinguish between the two test types and simply appends ms to the times.
    PROGRAM_NAME='MultipleTests'
    DEFINE_DEVICE
    
    dvTP	= 10001:1:0
    
    
    DEFINE_CONSTANT  //Benchmark Constants
    integer MAX_NUM_TESTS = 20;
    
    
    DEFINE_CONSTANT//Place test constants below
    DEFINE_TYPE //Place Test Types here
    
    
    DEFINE_VARIABLE	//Benchmark Variables DO NOT CHANGE
    char sTestDescription[MAX_NUM_TESTS][50]
    VOLATILE LONG 	lTL_Times[5] = {10000,10000,10000,10000,10000}
    LONG	lTestTime[MAX_NUM_TESTS][6] //1-5 = last values, 6 = running avg of all
    LONG	lTestTimeStart[MAX_NUM_TESTS][6] //1-5 = last values, 6 = running avg of all
    LONG	lTestTimeFinish[MAX_NUM_TESTS][6] //1-5 = last values, 6 = running avg of all
    LONG  lTestAverageCount[MAX_NUM_TESTS] = 0
    VOLATILE INTEGER nTestIndex[MAX_NUM_TESTS]
    VOLATILE INTEGER nWORK_IN_PROGRESS[MAX_NUM_TESTS]
    
    define_variable //Place Test Variables here
    volatile LONG nInfo[70000]
    
    LONG nLoop
    LONG nMax
    LONG Value1 = 1000;
    Long Value2 = 1500;
    
    //**********************
    //Benchmark functions. 
    //Call the TestStart function immediately before code to be tested.
    //Call the TestFinish function immediately after code to be tested.
    //**********************
    
    define_function TestName(integer nMethod, char sName[50]){
    	sTestDescription[nMethod] = sName;
    }
    define_function TestReset(integer nMethod){//Clears averages and sets pointers to first spot.
    	stack_var integer x;
    	
    	nTestIndex[nMethod] = 1;
    	nWORK_IN_PROGRESS[nMethod] = 0;
    	timeline_kill(nMethod);
    	lTestAverageCount[nMethod] = 0;
    	for(x=6;x;x--){
    		lTestTime[nMethod][x] = 0;
    	}
    	send_string 0,"'*********************************************************'";
    	send_string 0,"'* TEST ',itoa(nMethod),' RESET: ',sTestDescription[nMethod]";
    	send_string 0,"'*********************************************************'";
    }
    define_function TestStart(integer nMethod){
    	IF((nTestIndex[nMethod] > 5) or (nTestIndex[nMethod] < 1))
    		nTestIndex[nMethod] = 1;
    
    	send_string 0,"'*********************************************************'";
    	send_string 0,"'* TEST ',itoa(nMethod),' STARTING: ',sTestDescription[nMethod]";
    	send_string 0,"'*********************************************************'";
    
    	nWork_In_Progress[nMethod] = 1;
    	lTestTimeStart[nMethod][nTestIndex[nMethod]] = GET_TIMER; 
    	
    //	TIMELINE_CREATE(type_cast(nMethod),lTL_Times,5,TIMELINE_RELATIVE,TIMELINE_REPEAT);
    
    }
    define_function TestFinish(integer nMethod){
    	lTestTimeFinish[nMethod][nTestIndex[nMethod]] = GET_TIMER;
    	
    //	TIMELINE_PAUSE(nMethod);
    	lTestTime[nMethod][nTestIndex[nMethod]] = lTestTimeFinish[nMethod][nTestIndex[nMethod]] - lTestTimeStart[nMethod][nTestIndex[nMethod]];
    //	TIMELINE_KILL(nMethod);
    	lTestTime[nMethod][6] = ((lTestTime[nMethod][6]*lTestAverageCount[nMethod]) + lTestTime[nMethod][nTestIndex[nMethod]])/(lTestAverageCount[nMethod] + 1);
    	lTestAverageCount[nMethod]++;
    
    	send_string 0,"'*********************************************************'";
    	send_string 0,"'* TEST ',itoa(nMethod),' FINISHED: ',sTestDescription[nMethod]";
    	send_string 0,"'* Last run time: ',itoa(lTestTime[nMethod][nTestIndex[nMethod]]/10),'.',itoa(lTestTime[nMethod][nTestIndex[nMethod]]%10),'sec - ',sTestDescription[nMethod]";
    	send_string 0,"'* Average run time: ',itoa(lTestTime[nMethod][6]/10),'.',itoa(lTestTime[nMethod][6]%10),'sec - over ',itoa(lTestAverageCount[nMethod]),' tests - ',sTestDescription[nMethod]";
    	send_string 0,"'*********************************************************'";
    	
    	IF((nTestIndex[nMethod] >= 5) or (nTestIndex[nMethod] < 1))
    		nTestIndex[nMethod] = 1;
    	ELSE
    		nTestIndex[nMethod]++;
    	nWORK_IN_PROGRESS[nMethod] = 0;
    
    }
    define_function TestStart2(integer nMethod){
    	IF((nTestIndex[nMethod] > 5) or (nTestIndex[nMethod] < 1))
    		nTestIndex[nMethod] = 1;
    
    	send_string 0,"'*********************************************************'";
    	send_string 0,"'* TEST ',itoa(nMethod),' STARTING: ',sTestDescription[nMethod]";
    	send_string 0,"'*********************************************************'";
    
    	nWork_In_Progress[nMethod] = 1;
    //	lTestTimeStart[nMethod][nTestIndex[nMethod]] = GET_TIMER; 
    	
    	TIMELINE_CREATE(type_cast(nMethod),lTL_Times,5,TIMELINE_RELATIVE,TIMELINE_REPEAT);
    
    }
    define_function TestFinish2(integer nMethod){
    //	lTestTimeFinish[nMethod][nTestIndex[nMethod]] = GET_TIMER;
    	
    	TIMELINE_PAUSE(nMethod);
    	lTestTime[nMethod][nTestIndex[nMethod]] = TIMELINE_GET(nMethod);
    	TIMELINE_KILL(nMethod);
    	lTestTime[nMethod][6] = ((lTestTime[nMethod][6]*lTestAverageCount[nMethod]) + lTestTime[nMethod][nTestIndex[nMethod]])/(lTestAverageCount[nMethod] + 1);
    	lTestAverageCount[nMethod]++;
    
    	send_string 0,"'*********************************************************'";
    	send_string 0,"'* TEST ',itoa(nMethod),' FINISHED: ',sTestDescription[nMethod]";
    	send_string 0,"'* Last run time: ',itoa(lTestTime[nMethod][nTestIndex[nMethod]]),'ms - ',sTestDescription[nMethod]";
    	send_string 0,"'* Average run time: ',itoa(lTestTime[nMethod][6]),'ms - over ',itoa(lTestAverageCount[nMethod]),' tests - ',sTestDescription[nMethod]";
    	send_string 0,"'*********************************************************'";
    	
    	IF((nTestIndex[nMethod] >= 5) or (nTestIndex[nMethod] < 1))
    		nTestIndex[nMethod] = 1;
    	ELSE
    		nTestIndex[nMethod]++;
    	nWORK_IN_PROGRESS[nMethod] = 0;
    
    }
    define_function TestPrintReport(integer nMethod){
    	stack_var integer x;
    	
    	if(nMethod){
    		send_string 0,"'*********************************************************'";
    		send_string 0,"'* TEST ',itoa(nMethod),' REPORT: ',sTestDescription[nMethod]";
    		send_string 0,"'* Most recent 5 runs:'";
    		send_string 0,"'* 1: ',itoa(lTestTime[nMethod][1]),'ms'";
    		send_string 0,"'* 2: ',itoa(lTestTime[nMethod][2]),'ms'";
    		send_string 0,"'* 3: ',itoa(lTestTime[nMethod][3]),'ms'";
    		send_string 0,"'* 4: ',itoa(lTestTime[nMethod][4]),'ms'";
    		send_string 0,"'* 5: ',itoa(lTestTime[nMethod][5]),'ms'";
    		send_string 0,"'*----------------------------------------------------------'";
    		send_string 0,"'* Average run time: ',itoa(lTestTime[nMethod][6]),'ms - over ',itoa(lTestAverageCount[nMethod]),' tests'";
    		send_string 0,"'*********************************************************'";
    	}
    	else{
    		for(x=1;x<=MAX_NUM_TESTS;x++){ 
    			if(lTestTime[x][1]){
    				send_string 0,"'*********************************************************'";
    				send_string 0,"'* TEST ',itoa(x),' REPORT: ',sTestDescription[x]";
    				send_string 0,"'* Most recent 5 runs:'";
    				send_string 0,"'* 1: ',itoa(lTestTime[x][1]),'ms'";
    				send_string 0,"'* 2: ',itoa(lTestTime[x][2]),'ms'";
    				send_string 0,"'* 3: ',itoa(lTestTime[x][3]),'ms'";
    				send_string 0,"'* 4: ',itoa(lTestTime[x][4]),'ms'";
    				send_string 0,"'* 5: ',itoa(lTestTime[x][5]),'ms'";
    				send_string 0,"'*----------------------------------------------------------'";
    				send_string 0,"'* Average run time: ',itoa(lTestTime[x][6]),'ms - over ',itoa(lTestAverageCount[x]),' tests'";
    				send_string 0,"'*********************************************************'";
    			}
    		}
    	}
    }
    DEFINE_FUNCTION PutYourFunctionsBelow(){
    //example function for testing
    TestName(20,'Sample Test');//20 is the test ID. Change this accordingly. start at 1. MAX_NUM_TESTS is the highest ID allowed.
    TestStart(20);
    //Test code goes here!
    TestFinish(20);
    
    }
    DEFINE_FUNCTION forLoop1(){
    	TestName(1,'FOR (nLoop = 1; nLoop <= LENGTH_ARRAY(nInfo); nLoop++)');//20 is the test ID. Change this accordingly. start at 1. MAX_NUM_TESTS is the highest ID allowed.
    	TestStart(1);
    	FOR (nLoop = 1; nLoop <= LENGTH_ARRAY(nInfo); nLoop++)
    	{  
    		 nInfo[nLoop] = 1;
    	}  
    	TestFinish(1);
    
    }
    DEFINE_FUNCTION forLoop2(){
    	TestName(3,'FOR (nLoop = 1; nLoop <= MAX_LENGTH_ARRAY(nInfo); nLoop++)');//20 is the test ID. Change this accordingly. start at 1. MAX_NUM_TESTS is the highest ID allowed.
    	TestStart(3);
    	  FOR (nLoop = 1; nLoop <= MAX_LENGTH_ARRAY(nInfo); nLoop++)
    	  {  
    		 nInfo[nLoop] = 2;
    	  }  
    	TestFinish(3);
    
    }
    DEFINE_FUNCTION forLoop3(){
    	TestName(4,'FOR (nLoop = 1, nMax = MAX_LENGTH_ARRAY(nInfo); nLoop <= nMax; nLoop++)');//20 is the test ID. Change this accordingly. start at 1. MAX_NUM_TESTS is the highest ID allowed.
    	TestStart(4);
    	  FOR (nLoop = 1, nMax = MAX_LENGTH_ARRAY(nInfo); nLoop <= nMax; nLoop++)
    	  {  
    		 nInfo[nLoop] = 4;
    	  }  
    	TestFinish(4);
    
    }
    DEFINE_FUNCTION forLoop4(){
    	TestName(5,'FOR (nLoop = MAX_LENGTH_ARRAY(nInfo); nLoop > 0; nLoop--)');//20 is the test ID. Change this accordingly. start at 1. MAX_NUM_TESTS is the highest ID allowed.
    	TestStart(5);
    	  FOR (nLoop = MAX_LENGTH_ARRAY(nInfo); nLoop > 0; nLoop--)
    	  {  
    		 nInfo[nLoop] = 8
    	  }  
    	TestFinish(5);
    
    }
    DEFINE_FUNCTION forLoop5(){
    	TestName(6,'FOR (nLoop = MAX_LENGTH_ARRAY(nInfo); nLoop; nLoop--)');//20 is the test ID. Change this accordingly. start at 1. MAX_NUM_TESTS is the highest ID allowed.
    	TestStart(6);
    	  FOR (nLoop = MAX_LENGTH_ARRAY(nInfo); nLoop; nLoop--)
    	  {
    		 nInfo[nLoop] = 16
    	  }
    	TestFinish(6);
    
    }
    DEFINE_FUNCTION forLoop6(){
    	stack_var long snLoop;
    
    	TestName(7,'FOR (snLoop = MAX_LENGTH_ARRAY(nInfo); snLoop; snLoop--)');//20 is the test ID. Change this accordingly. start at 1. MAX_NUM_TESTS is the highest ID allowed.
    	TestStart(7);
    	  FOR (snLoop = MAX_LENGTH_ARRAY(nInfo); snLoop; snLoop--)
    	  {
    		 nInfo[snLoop] = 32
    	  }
    	TestFinish(7);
    
    }
    DEFINE_FUNCTION forLoop7(){
    	stack_var long snLoop;
    	
    	TestName(2,'FOR (snLoop = 1; snLoop <= LENGTH_ARRAY(nInfo); snLoop++)');//20 is the test ID. Change this accordingly. start at 1. MAX_NUM_TESTS is the highest ID allowed.
    	TestStart(2);
    	  FOR (snLoop = 1; snLoop <= LENGTH_ARRAY(nInfo); snLoop++)
    	  {  
    		 nInfo[snLoop] = 64;
    	  }  
    	TestFinish(2);
    
    }
    DEFINE_FUNCTION onVsTrue(){
    	stack_var long snLoop;
    	
    	TestName(8,'nInfo[nLoop]=TRUE .. nInfo[nLoop]=FALSE');//20 is the test ID. Change this accordingly. start at 1. MAX_NUM_TESTS is the highest ID allowed.
    	TestStart(8);
    	  FOR (nLoop = Value1; nLoop; nLoop--)
    	  {
    		nInfo[nLoop] = TRUE;
    		nInfo[nLoop] = FALSE;
    	  }
    	TestFinish(8);
    	TestName(9,'nInfo[nLoop]=TRUE .. nInfo[nLoop]=FALSE');//20 is the test ID. Change this accordingly. start at 1. MAX_NUM_TESTS is the highest ID allowed.
    	TestStart(9);
    	  FOR (nLoop = Value2; nLoop; nLoop--)
    	  {
    		nInfo[nLoop] = TRUE;//1;
    		nInfo[nLoop] = FALSE;//0;
    	  }
    	TestFinish(9);
    	TestName(10,'ON[nInfo[nLoop]] .. OFF[nInfo[nLoop]]');//20 is the test ID. Change this accordingly. start at 1. MAX_NUM_TESTS is the highest ID allowed.
    	TestStart(10);
    	  FOR (nLoop = MAX_LENGTH_ARRAY(nInfo); nLoop; nLoop--)
    	  {
    		ON[nInfo[nLoop]];
    		OFF[nInfo[nLoop]];
    	  }
    	TestFinish(10);
    
    	TestName(11,'nInfo[nLoop]=TRUE .. nInfo[nLoop]=FALSE');//20 is the test ID. Change this accordingly. start at 1. MAX_NUM_TESTS is the highest ID allowed.
    	TestStart2(11);
    	  FOR (nLoop = Value1; nLoop; nLoop--)
    	  {
    		nInfo[nLoop] = TRUE;
    		nInfo[nLoop] = FALSE;
    	  }
    	TestFinish2(11);
    	TestName(12,'nInfo[nLoop]=TRUE .. nInfo[nLoop]=FALSE');//20 is the test ID. Change this accordingly. start at 1. MAX_NUM_TESTS is the highest ID allowed.
    	TestStart2(12);
    	  FOR (nLoop = Value2; nLoop; nLoop--)
    	  {
    		nInfo[nLoop] = TRUE;//1;
    		nInfo[nLoop] = FALSE;//0;
    	  }
    	TestFinish2(12);
    	TestName(13,'ON[nInfo[nLoop]] .. OFF[nInfo[nLoop]]');//20 is the test ID. Change this accordingly. start at 1. MAX_NUM_TESTS is the highest ID allowed.
    	TestStart2(13);
    	  FOR (nLoop = MAX_LENGTH_ARRAY(nInfo); nLoop; nLoop--)
    	  {
    		ON[nInfo[nLoop]];
    		OFF[nInfo[nLoop]];
    	  }
    	TestFinish2(13);
    
    }
    
    
    DEFINE_START
    SET_LENGTH_ARRAY (nInfo,70000)
    
    
    DEFINE_EVENT
    BUTTON_EVENT[dvTP,1] {  //Run Test
    
       PUSH: {
    		stack_var integer x;
    		for(x=5;x;x--){
    			forLoop1();
    			forLoop2();
    			forLoop3();
    			forLoop4();
    			forLoop5();
    			forLoop6();
    			forLoop7();
    			onVsTrue();
    		}
       }
    }
    BUTTON_EVENT[dvTP,2] { //Run Test
       PUSH: {
    		stack_var integer x;
    		for(x=5;x;x--){
    			onVsTrue();
    		}
       }
    }
    BUTTON_EVENT[dvTP,3] { //Run Test
       PUSH: {
       }
    }
    
    BUTTON_EVENT[dvTP,100] 
    BUTTON_EVENT[dvTP,101] 
    BUTTON_EVENT[dvTP,102] 
    BUTTON_EVENT[dvTP,103] 
    BUTTON_EVENT[dvTP,104] 
    BUTTON_EVENT[dvTP,105] 
    BUTTON_EVENT[dvTP,106] 
    BUTTON_EVENT[dvTP,107] 
    BUTTON_EVENT[dvTP,108] 
    BUTTON_EVENT[dvTP,109] 
    BUTTON_EVENT[dvTP,110] 
    BUTTON_EVENT[dvTP,111] 
    BUTTON_EVENT[dvTP,112] 
    BUTTON_EVENT[dvTP,113] 
    BUTTON_EVENT[dvTP,114] 
    BUTTON_EVENT[dvTP,115] 
    BUTTON_EVENT[dvTP,116] 
    BUTTON_EVENT[dvTP,117] 
    BUTTON_EVENT[dvTP,118] 
    BUTTON_EVENT[dvTP,119] 
    BUTTON_EVENT[dvTP,120]{  //Print reports. channel 100 prints all valid reports.
    						//channel 101-120 print a report only for a single test (channel-100)
                     
       PUSH: {
    		TestPrintReport(button.input.channel - 100);
       }
    }
    button_event[dvTp,255]{ //Reset Test Data
    	push:{
    		stack_var integer x;
    		for(x=MAX_NUM_TESTS;x;x--){
    			TestReset(x);
    		}
    	}            
    }
    

    Jeff
  • Joe HebertJoe Hebert Posts: 2,159
    Spire_Jeff wrote:
    That is what I thought, the only thing I can think of is that maybe TRUE and FALSE are treated as boolean instead of integers?
    Netlinx doesn?t support a Boolean data type. TRUE and FALSE are declared as CHARs in Netlinx.axi. I changed the variable nVar in my test program from an INTEGER to a CHAR and it made absolutely no difference in the results.
    Spire_Jeff wrote:
    I think I see the problem and the reason I wound up using timelines. Timelines have a higher resolution than GET_TIMER. GET_TIMER has a resolution of only .1 seconds. Timelines allow for .001 seconds
    Spire_Jeff wrote:
    Tests 8 and 11 are looped 1000 times, tests 9 and 12 are looped 1500 times.
    I don?t feel loops that only last milliseconds collect anywhere near enough data to draw solid conclusions. The FOR loops I tested with were 1 million times round trip When tests last for 20 seconds plus, measuring to the tenth of a second or to a thousand of a second doesn?t make much of a difference. If my math is correct that?s about ? of 1 percent possible margin of difference or at most ? of 1 percent.

    If your test methods still support that 1/0 is slower than TRUE/FALSE, I just can?t buy it. I also believe the simpler and least obstructive testing method works best. We?ll simply have to agree to disagree.

    Whatever the case, I?m not going to be afraid to use ON/OFF, TRUE/FALSE, or 1/0 because all we?re really doing in the big scheme of things is contesting (discussing) at most a drop of water in the ocean with this one. It sure isn?t going to make any difference in your code that takes 25 minutes to boot. :) Man that?s over the top crazy unless you have a boat load of Duet modules in that program, even still...
Sign In or Register to comment.