Your Universal Remote Control Center
RemoteCentral.com
Philips Pronto Professional Forum - View Post
Previous section Next section Previous page Next page Up level
What's New
11/18/09 - A major update brings our collection to over 1,350 manuals for 115 brands.
11/04/09 - New features, hundreds of 2-way and RS-232 modules, plus a web browser for the MX-6000.
9/04/09 - Latest activity-based model features a color screen at an economical price.
9/03/09 - * OK, one string – you may have to learn something!
8/22/09 - As it turns out, those who do not learn from history... still won't repeat it.

Up level
The following page was printed from RemoteCentral.com:

Login:
Pass:
 
 

Page 2 of 3
Topic:
Optimize your Prontoscript!!!
This thread has 32 replies. Displaying posts 16 through 30.
Post 16 made on Wednesday October 21, 2009 at 04:20
Sogliphy
Regular Member
Joined:
Posts:
July 2007
100
On October 20, 2009 at 10:56, Lyndel McGee said...
By chance, did you try your test with 10000 operations compared to running a normal loop? Last time I tried a test using foreach, I was severely disappointed because the overhead of calling the function was more costly than setting up the normal loop.

Not trying to show anyone up here. I just don't want folks to think that just because there's a synctactically, sugarful, easy way to do things that it is the most performant.

Lyndel, you were right: forEach is slower than iterating with an index. It does make sense for smaller arrays, especially if they are defined in-line, because of parsing being faster, i.e.:

["ALPHA", "BETA"].forEach(function(w) { GUI.widget(w).visible = false; });
Post 17 made on Thursday October 22, 2009 at 02:11
Lyndel McGee
RC Moderator
Joined:
Posts:
August 2001
9,152
For readability, maybe but, as you discovered, the function call overhead is really way too much, especially since you are compiling BOTH an array AND an anonymous function each time you execute forEach.

If you MUST use such an approach, here's my suggestion:

// function and array defined somewhere such as at the application and/or page level.
function hide(w){GUI.widget(w).visible = false;}
var widgetTags = ["ALPHA","BETA"];

// code inside Activity, Page, or Button Script or function that gets executed at least more than one time. This way, you compile the array AND function only 1 time.
widgetTags.forEach(hide);
Lyndel McGee
Philips Pronto Addict/Beta Tester
View EscientPronto 1.0.2 Docs - [Link: mediafire.com]
Post 18 made on Thursday October 22, 2009 at 06:28
Sogliphy
Regular Member
Joined:
Posts:
July 2007
100
On October 22, 2009 at 02:11, Lyndel McGee said...
For readability, maybe but, as you discovered, the function call overhead is really way too much, especially since you are compiling BOTH an array AND an anonymous function each time you execute forEach.

No, the array and the function are compiled once (to SpiderMonkey byte code). There is the only the overhead of instantiating a function closure for every iteration.
Post 19 made on Friday October 23, 2009 at 18:04
Lyndel McGee
RC Moderator
Joined:
Posts:
August 2001
9,152
On October 22, 2009 at 06:28, Sogliphy said...
No, the array and the function are compiled once (to SpiderMonkey byte code). There is the only the overhead of instantiating a function closure for every iteration.

I stand corrected. :-)
Lyndel McGee
Philips Pronto Addict/Beta Tester
View EscientPronto 1.0.2 Docs - [Link: mediafire.com]
Post 20 made on Monday November 2, 2009 at 17:44
Rusty Fobe
Junior Member
Joined:
Posts:
December 2008
42
I never saw anyone of you using "while" instead of "for". I always use "while" because I find it more readable. Since I only have short iterations it doesn't matter so much, so I'll stick to "while", but I'm curious to see your answer... just in case I have to get better performance. So, is "for" more efficient in running time than "while" ?

i=0;
j=0;
while (i if (favorites[i]) {
preferred[j]=favorites[i];
j++;}
i++;}
Post 21 made on Monday November 2, 2009 at 20:17
Lyndel McGee
RC Moderator
Joined:
Posts:
August 2001
9,152
Rusty,

Try it out with a loop of say 10000 iterations and report back the time diffs.
Lyndel McGee
Philips Pronto Addict/Beta Tester
View EscientPronto 1.0.2 Docs - [Link: mediafire.com]
Post 22 made on Tuesday November 3, 2009 at 11:50
Rusty Fobe
Junior Member
Joined:
Posts:
December 2008
42
Well Lyndel, I took the challenge and enjoyed writing a test program that you will find below the test results. Rusty
PS. I note that in preview mode some of the code disappears "(while (n" instead of "while (n<eMax-eMin) {", although I've set it to "computer code". I hope this does not happen when I post the response.

The results will differ all the time if you run it several times. Specialists among you, I hope I wrote the program in a correct way. The actual test is only 2 lines of code marked by test start and ends here.

I only copied the end result and one detailed result. The output gives details per iteration cycle.
I used powers of 2 starting with 4096 iterations, each time doubling up to 1048576.
Below you see one of the 10 passes, each pass yields different results.

#iterationsforwhileresultpass #8
4096015result is not reliable
8192016result is not reliable
16384163148.4for is faster
3276831310both are equally fast
6553662631.6for is faster
13107212514111.3for is faster
2621442662506.0while is faster
5242885155002.9while is faster
1048576101510321.6for is faster

The program executes such a series 10 times, and concluded with the following:

processed 2093056 iterations in 3 tests described above

for needed 20892 ms
while needed 20905 ms
a difference of 0.01 seconds on a total of 21 seconds

for needed 20531 ms
while needed 21110 ms
a difference of 0.58 seconds on a total of 21 seconds

for needed 22046 ms
while needed 21781 ms
a difference of 0.27 seconds on a total of 22 seconds

I did not test it using the remote control.
If anyone wants to try this too: just copy the program to a button in an empty configuration and follow the results in ProntoScript Console. Be careful when changing the limits, look at the comment about processing time (next to pMax=10).

var d; // date
var f; // for, time in ms
var w; // while, time in ms
var i; // iterations, set by 2 to the power of e
var e; // exponent
var eMin; // exponent minimum
var eMax; // exponent maximum
var step; // =e-eMin
var n; // iteration counter
var r; // result in %, result=100*absolute(for-while)/while )
var c; // conditional text
var p; // pass number
var pMax; // maximum number of passes
var x; // total number of iterations
var fVector=[]; // contains results of all passes for for
var wVector=[]; // contains results of all passes for while
var pVector=[]; // contains number valid iterations per pass

var showEach=true; // set to true to get details of each pass, next to the average result
eMin=12; // lower values are not reliable
eMax=21; // higher values cause longer wait time (depending on processor speed)
pMax=10; // processing time is equivalent to p*sigma(2 to the power of e), where e = 12 up to 20  !!

// initiate vectors
n=0;
while (n<eMax-eMin) {
   fVector[n]=0;
   wVector[n]=0;
   pVector[n]=pMax;
   n++;}

p=0;

// watch the result in ProntoScript Console

while (p<pMax) {
   System.print(showEach?("\n#iterations\tfor\twhile\tresult\tpass #"+p):("processing pass #"+p))
   e=eMin;
   
   while (e<eMax) {
      i=Math.pow(2,e)
      
      //test starts here
      d=new Date().getTime();n=0;while(n<i){n++;};w=new Date().getTime()-d; 
      d=new Date().getTime();for(n=0;n<i;n++){};f=new Date().getTime()-d;
      // test ends here
      
      if (showEach) {
display()}
      step=e-eMin
      if (f==0 | w==0) {
pVector[step]--}
      else {
fVector[step]=fVector[step]+f;
wVector[step]=wVector[step]+w;
// System.print("fVector "+fVector+" wVector "+wVector);
}
      e++;}
   p++;}
   
e=eMin;
x=0;
while (e<eMax){
   x=x+Math.pow(2,e);
   e++;}
   
System.print("\naverages of "+pMax+" passes = "+x+" iterations")
System.print("#iterations\tfor\twhile\tresult(%)")

e=eMin;
while (e<eMax) {
   i=Math.pow(2,e);
   step=e-eMin
   f=fVector[step]/pVector[step];
   w=wVector[step]/pVector[step];
   f=f.toFixed(0);
   w=w.toFixed(0);
   display();
   e++;}

e=eMin;
f=0;
w=0;
while (e<eMax) {
   i=Math.pow(2,e);
   step=e-eMin
   f=f+fVector[step];
   w=w+wVector[step];
   e++;}
   
System.print("\nto process "+x+" iterations");
System.print("for\tneeded "+f+" ms");
System.print("while\tneeded "+w+" ms");
System.print("a difference of "+(Math.abs(f-w)/1000).toFixed(2)+" seconds on a total of "+((f+w)/2000).toFixed(0)+" seconds");
System.print("\nend of test\n");

function display () {
// display results
      if (f==0 | w==0) {
         r=""
         c="result is not reliable"}
      else {
         if (f==w) {
            r=0;
            c="both are equally fast"}
         else {
            if (f<w) {
      r=(100*Math.abs(f-w)/w).toFixed(1);
      c="for is faster"}
   else {
      r=(100*Math.abs(w-f)/f).toFixed(1);
      c="while is faster"}}}
         
      System.print(i+"\t\t"+f+"\t"+w+"\t"+r+"\t"+c);
}
 
Post 23 made on Tuesday November 3, 2009 at 19:23
Lyndel McGee
RC Moderator
Joined:
Posts:
August 2001
9,152
Rusty,

Thank you soooo much for the thorough analysis. My time these days has been very limited and I've not had as much time to "play".

For those of you who may wonder why Rusty posted the above stuff...

This is really what it takes to make assessments about how to optimize code. A THOROUGH analysis.

Sometimes one thing is faster and sometimes other things are faster. All in all, optimization lies in the hands of the program author. There is really no magic bullet other than to know what the code is doing.

To improve initial compilation/interpretation times as well as runtime performance, you can usually remove comments (compilation) and use short variable/function names (compilation and runtime). Beyond that, you really need to write some code and try it out either in the sim or on the remote.

Sometimes, you will find a tip on the web (google or yahoo searches) but you have to be careful as the timings they report, especially if tested on Internet Explorer are NOT tested using the same version of Javascript that runs in the Pronto. IE, for example, has MS enhancements (JScript) and is not a pure Spidermonkey (Javascript in use by Pronto) implementation.
Lyndel McGee
Philips Pronto Addict/Beta Tester
View EscientPronto 1.0.2 Docs - [Link: mediafire.com]
Post 24 made on Wednesday November 4, 2009 at 08:05
mraneri
Regular Member
Joined:
Posts:
February 2009
113
I have found, you cannot compare ANY test in any browser or the simulator to a test executed on the pronto. The results don't correlate. I have found you must download to the pronto to profile any code. I have found the pronto runs 100 to 10000 times slower than the simulator (on my PC), depending on what I'm profiling...

Also, I have found generally very consistent results.. Again, depending on what I'm doing, I get similar execution times when I iterate 100 times compared to when I iterate 1000 times. (Per iteration). and I always report (to myself) execution time per iteration (for my own sanity).
Post 25 made on Wednesday November 4, 2009 at 11:00
Rusty Fobe
Junior Member
Joined:
Posts:
December 2008
42
That's right Mike. I downloaded the test I posted earlier in this thread to the Pronto, but I ensured first to take down the number of iterations to about 10000, instead of the 2 million on a PC. The Pronto would probably stop responding.

If code A runs faster than code B on a PC, it might run faster on a Pronto as well. Indeed, that is no guarantee. I have seen strange effects of processors on runtime during my career. Did you find a consistencies or anomalies between your PC and the Pronto regarding runtime ? I'm not that far yet.
Post 26 made on Wednesday November 4, 2009 at 13:24
Rusty Fobe
Junior Member
Joined:
Posts:
December 2008
42
Update: improved test, as result of Mike's mail.

On my second hand 1.6 GHz PC, running XP
note: 2048 is missing in the first, because testB gave an unreliable result (0 ms)
I think that if getting time before & after a test case is within the timespan of the same 15 ms, times are equal.
The µs = ms/#iterations. Mike was right, µs give more insight in the Pronto behaviour.

The test on the PC shows that the average time drops drastically when the number of iterations increase
from 1024 to 4096 & 8192, then two small gains before it gets more or less stable from 32768 iterations.

The test on the Pronto shows that the average time drops drastically when the number of iteration increase
from 32 to about 256 (testB), then it remains more or less stable with one exception in test B.

The test was simple:
function testA() {var a=1000; a=a+a;a=a-a;}
function testB() {var a=1000; a=a*a; a=a/a;}

As well on the PC as on the Pronto both tests yielded about the same result: speed difference between testA and TestB
is lower than 1% which is not significant enough to tell that the +- test is faster than */-test on PC or Pronto.
This can be different with other PC's or other instruction sets.

You find the improved program below the results. With this program you can compare two sets of instructions.


averages of 10 passes = 20886528 iterations
#iterationstestAtestBresult(%)
102415ms 14.65µs16ms 15.63µs6.3A is faster
409632ms 7.81µs15ms 3.66µs53.1B is faster
819219ms 2.32µs18ms 2.20µs5.3B is faster
1638436ms 2.20µs31ms 1.89µs13.9B is faster
3276866ms 2.01µs62ms 1.89µs6.1B is faster
65536131ms 2.00µs127ms 1.94µs3.1B is faster
131072258ms 1.97µs255ms 1.95µs1.2B is faster
262144509ms 1.94µs508ms 1.94µs0.2B is faster
5242881010ms 1.93µs1010ms 1.93µs0both are equally fast
10485762023ms 1.93µs2020ms 1.93µs0.1B is faster

to process 20886528 iterations
testAneeded 40546 ms, i.e. 1.94µs per iteration
testBneeded 40315 ms, i.e. 1.94µs per iteration
a difference of 0.23 seconds (0.57%) on a total of 40.55 seconds


On the Pronto

averages of 10 passes = 327598 iterations
#iterationstestAtestBresult(%)
322ms 62.50µs2ms 62.50µs0both are equally fast
643ms 46.88µs4ms 62.50µs25.0A is faster
1287ms 54.69µs7ms 54.69µs0both are equally fast
25613ms 50.78µs14ms 54.69µs7.1A is faster
51226ms 50.78µs27ms 52.73µs3.7A is faster
102453ms 51.76µs53ms 51.56µs0both are equally fast
2048106ms 51.76µs113ms 55.18µs6.2A is faster
4096211ms 51.51µs212ms 51.76µs0.5A is faster
8192422ms 51.51µs423ms 51.64µs0.2A is faster
16384845ms 51.57µs845ms 51.57µs0both are equally fast

to process 327598 iterations
testAneeded 16912 ms, i.e. 51.62µs per iteration
testBneeded 17004 ms, i.e. 51.62µs per iteration
a difference of 0.09 seconds (0.54%) on a total of 17.00 seconds

It would have taken 1084 seconds to run the 20886528 iterations on the Pronto

And here is the program:
 
function testA(){

}

function testB(){

}

// ------------------------ do not change the code below this line --------------------------
// HOW TO
// put code to be compared on performance inside testA & testB like shown
// if the code contains iterations, lower the values eMin and eMax to avoid very long wait times
// if the code contains heavy iterations consider putting eMin to 0 and eMax to 5 (for example)

// USE MODES
// dyadic use >> shows runtimes of code A versus code B, including the runtime of the iteration itself
// monadic use >> testB empty: shows runtime of code A including the iteration runtime, B shows iteration runtime
// niladic use >> testA & testB empty: should yield equal iteration runtimes; reality is different: read the remark

// REMARK
// note that any interference disturbs the test: run this without code and without touching mouse & keyboard
// there will be a difference in runtime even if the code is exactly the same
// now try this: enlarge the ProntoScript Console by dragging it with the mouse during a test
// you will notice a signicant difference in one of the tests

// EXAMPLE
// dyadic use: testA contained: var a=1000; a=a+a;a=a-a; testB contained: var a=1000; a=a*a; a=a/a;
//to process 2093056 iterations
//testAneeded 40640 ms
//testBneeded 40594 ms
//a difference of 0.05 seconds (0.12%) on a total of 41 seconds
//>>> proves that there is no difference in speed between +- and */
//
// monadic use: testA contained: var a=1000; a=a+a;a=a-a; testB was left empty
//to process 2093056 iterations
//testAneeded 40329 ms
//testBneeded 22344 ms
//a difference of 17.98 seconds (44.58%) on a total of 40.32 seconds
//>>> shows that the code in testA takes 18 seconds, while the iteration by itself required already 22 seconds

test();

function test() {
   var d; // date
   var a; // testA runtime in ms
   var b; // testB runtime in ms
   var i; // iterations, set by 2 to the power of e
   var e; // exponent
   var eMin; // exponent minimum
   var eMax; // exponent maximum
   var step; // =e-eMin
   var n; // iteration counter
   var r; // result in %, result=100*absolute(for-while)/while )
   var c; // conditional text
   var p; // pass number
   var pMax; // maximum number of passes
   var x; // total number of iterations
   var aVector=[]; // contains results of all passes for testA
   var bVector=[]; // contains results of all passes for testB
   var pVector=[]; // contains number valid iterations per pass

   var showEach=true; // set to true to get details of each pass, next to the average result
   eMin=10; // lower values are not reliable
   eMax=15; // higher values cause longer wait time (depending on processor speed)
   pMax=10; // processing time is equivalent to p*sigma(2 to the power of e), where e = 12 up to 20  !!

   // initiate vectors
   n=0;
   while (n<eMax-eMin) {
      aVector[n]=0;
      bVector[n]=0;
      pVector[n]=pMax;
      n++;}

   p=0;

   // watch the result in ProntoScript Console

   while (p<pMax) {
      System.print(showEach?("\n#iterations\ttestA\t\ttestB\t\tresult\tpass #"+p):("processing pass #"+p))
      e=eMin;
   
      while (e<eMax) {
         i=Math.pow(2,e)
      
         //test starts here
d=new Date().getTime();n=0;while(n<i){testA();n++;};a=new Date().getTime()-d;  
         d=new Date().getTime();n=0;while(n<i){testB();n++;};b=new Date().getTime()-d; 
         // test ends here
      
step=e-eMin;
         if (a==0 | b==0 | a==NaN | b==NaN) {
   pVector[step]--;}
else {
   if (showEach) {
      display(a,b,c,i,r)}
 
   aVector[step]=aVector[step]+a;
   bVector[step]=bVector[step]+b;
   // System.print("aVector "+aVector+" bVector "+bVector);
   }
         e++;}
      p++;}
   
   x=0;
   p=0;
   while (p<eMax-eMin){
      x=x+pVector[p]*Math.pow(2,eMin+p);
      p++;}
      
   System.print("\naverages of "+pMax+" passes = "+x+" iterations")
   System.print("#iterations\ttestA\t\ttestB\t\tresult(%)")

   e=eMin;
   while (e<eMax) {
      i=Math.pow(2,e);
      step=e-eMin;
      if (pVector[step]>0){
a=(aVector[step]/pVector[step]).toFixed(0);
b=(bVector[step]/pVector[step]).toFixed(0);
display(a,b,c,i,r);}
      e++;}

   e=eMin;
   a=0;
   b=0;
   while (e<eMax) {
      i=Math.pow(2,e);
      step=e-eMin;
      a=a+aVector[step];
      b=b+bVector[step];
      e++;}
   
   System.print("\nto process "+x+" iterations");
   System.print("testA\tneeded "+a+" ms, i.e. "+(1000*a/x).toFixed(2)+"µs per iteration");
   System.print("testB\tneeded "+b+" ms, i.e. "+(1000*a/x).toFixed(2)+"µs per iteration");
   r=((a>b)?a:b)/1000;
   n=(Math.abs(a-b)/1000);
   System.print("a difference of "+n.toFixed(2)+" seconds ("+(100*n/r).toFixed(2)+"%) on a total of "+r.toFixed(2)+" seconds");
   System.print("\nend of test\n");
}

function display (a,b,c,i,r) {
// display results
      if (a==0 | b==0 | a==NaN | b == NaN) {
         r=""
         c="result is not reliable"}
      else {
         if (a==b) {
            r=0;
            c="both are equally fast"}
         else {
            if (a<b) {
      r=(100*Math.abs(a-b)/b).toFixed(1);
      c="A is faster"}
   else {
      r=(100*Math.abs(b-a)/a).toFixed(1);
      c="B is faster"}}}
         
      System.print(i+"\t\t"+a+"ms "+(1000*a/i).toFixed(2)+"µs\t"+b+"ms "+(1000*b/i).toFixed(2)+"µs\t"+r+"\t"+c);
}
 
Post 27 made on Thursday November 5, 2009 at 07:55
mraneri
Regular Member
Joined:
Posts:
February 2009
113
On November 4, 2009 at 11:00, Rusty Fobe said...
Did you find a consistencies or anomalies between your PC and the Pronto regarding runtime ? I'm not that far yet.

Rusty,
Actually, the experiment I spent a lot of time on (Optimizing the UTF8 Routine I posted at the beginning) was effectively operating on an array of short strings. I couldn't really scale it to huge array sizes in the simulator cause I feared Memory allocation issues would completely invalidate the results, so I did all the optimization on the pronto. Also, as noted in the initial e-mail, there were other optimizations in the iteration itself (the for loop), so It was just more straightforward to download to the pronto when I was ready to check the speed.

However, I have found that while stuff that generally runs faster on the PC generally runs faster on the pronto, the amount of gain you get on one platform doesn't relate that much to the amount of gain you get on the other.

- Mike
Post 28 made on Thursday November 5, 2009 at 12:02
Rusty Fobe
Junior Member
Joined:
Posts:
December 2008
42
Thanks Mike. By the way, I found a following link that could be interesting for UTF-8 decoding. Looks to be an interesting approach. I am absolutely not familiar with decoding and chunking etc. So I cannot judge about its value.

www.lookout.net/2009/04/24/ultrafast-utf-8-decoder-by-bjoern-hoehrmann/

Post 29 made on Friday November 6, 2009 at 05:41
Sogliphy
Regular Member
Joined:
Posts:
July 2007
100
On October 13, 2009 at 22:35, mraneri said...
            c = c.substr(0,i)+String.fromCharCode((64*(c.charCodeAt(i) & 31) +
                (c.charCodeAt(i+1) & 63)) & 255)+c.substr(i+2);

I think this line should be changed into:


c = c.substr(0,i)+String.fromCharCode((64*(c.charCodeAt(i) & 31) +
(c.charCodeAt(i+1) & 63)) & 4095)+c.substr(i+2);


Otherwise, the following UTF-8 test sequence:

"Irish: \"An \xe1\xb8\x83fuil do \xc4\x8bro\xc3\xad ag";

won't be properly converted to:

"Irish: \"An \u1e03fuil do \u010bro\u00ed ag";
Post 30 made on Friday November 6, 2009 at 08:08
mraneri
Regular Member
Joined:
Posts:
February 2009
113
Sogliphy, I believe you are right. I will check it out and update the code.

Rusty, I checked the link. There's definitely some interesting stuff going on in there, however, that method still requires looping through the entire string... Something which is tremendously slow in interpreted javascript. My method, which basically uses a precompiled loop (by way of the regexp call) is much faster, because the looping and char comparisons are done in compiled code.

Given the interpreted javascript method, the performance hit isn't hard to see, when you realize each character, one at a time, is being converted to a double precision floating point value (in .charCodeAt), and compared to another double for each iteration through the loop.

- Mike
Page 2 of 3


Jump to


Protected Feature Before you can reply to a message...
You must first register for a Remote Central user account - it's fast and free! Or, if you already have an account, please login now.

Please read the following: Unsolicited commercial advertisements are absolutely not permitted on this forum. Other private buy & sell messages should be posted to our Marketplace. For information on how to advertise your service or product click here. Remote Central reserves the right to remove or modify any post that is deemed inappropriate.

Hosting Services by ipHouse