Results 1 to 8 of 8

Thread: setTimeout vagaries

  1. #1
    Join Date
    Mar 2005
    Location
    SE PA USA
    Posts
    30,495
    Thanks
    82
    Thanked 3,449 Times in 3,410 Posts
    Blog Entries
    12

    Default setTimeout vagaries

    Ever notice how in scripts where you do something like (snippet based loosely upon my updated version of Circling text trail script originally by Tim Tilton):

    Code:
    function drag(){
     y[0] = Math.round(Y[0] += ((ymouse) - Y[0]) * speed);
     x[0] = Math.round(X[0] += ((xmouse) - X[0]) * speed);
     for (var i = n; i > 0; --i){
      y[i] = Math.round(Y[i] += (y[i-1] - Y[i]) * speed);
      x[i] = Math.round(X[i] += (x[i-1] - X[i]) * speed);
     };
     makecircle();
    setTimeout(drag, 20);
    }
    that different browsers run the code at different speeds?

    Well, I have and it has always bothered me. I got this inspiration though just recently to test the timeout interval against instances of the Date object and to adjust said timeout interval based upon that (actual code snippets):

    Code:
    var n = msg.length - 1, a = Math.round(size * diameter * 0.208333), inv = 20, unv = inv,
    Code:
    drag = function(){ // makes the resistance
    if(abstime.l && abstime.l > 0)
    abstime(abstime.a || false);
     y[0] = Math.round(Y[0] += ((ymouse) - Y[0]) * speed);
     x[0] = Math.round(X[0] += ((xmouse) - X[0]) * speed);
     for (var i = n; i > 0; --i){
      y[i] = Math.round(Y[i] += (y[i-1] - Y[i]) * speed);
      x[i] = Math.round(X[i] += (x[i-1] - X[i]) * speed);
     };
     makecircle();
    setTimeout(drag, unv);
    },
    Code:
    abstime = function(be){
    abstime.l--;
     if(be) abstime.b = new Date();
     else abstime.e = new Date();
     if (abstime.b && abstime.e && abstime.l && abstime.l > 0){
      abstime.ms = Math.abs(abstime.b.valueOf() - abstime.e.valueOf());
      unv = abstime.ms > inv? unv - 1 : abstime.ms < inv? unv + 1 : unv;
      abstime.ar[abstime.ar.length] = abstime.ms;
      }
     else if(abstime.ms) unv = Math.round(eval(abstime.ar.join('+')) / abstime.ar.length);
    abstime.a = !abstime.a;
    };
    
    abstime.l = 100;
    abstime.ar = [];
    What this does for the first 99 or so iterations of the code is test the actual intended timeout interval (inv, 20 in this case) against the actual time elapsed between each execution, and adjust the used timeout interval (unv) up or down to attempt to achieve the intended interval.

    After the 99 or so tries, abstime sets the timeout interval based upon an average of all the tries which were stored in the abstime.ar array, and then stops checking and adjusting things, so it is really a very small addition to the code execution wise.

    I was surprised that this actually worked (got various browsers to perform at the virtually same speed, at least as far as the eye could tell), and even more so that the value arrived at was always about the same (+-1, 23/24, in this case) regardless of browser, and a higher value than I would have expected for any of them except the fastest one.

    What I concluded from this (borne out by testing) was that on my system 20 was too short of a timeout interval, had I just used 23 or 24 to begin with, it would have been just fine without all this extra code. But what about other computers?

    And, with this added code (or simply using 24) the script ran much more smoothly in the browser (FF) where it had been fast and a bit jerky at 20.

    This leads me to believe that the famed jerkiness (for many javascript animation type actions) in FF is a result of it actually trying to adhere to set intervals rather than adapting them to what it can actually do smoothly. IE and others (Safari, Opera) appeared to adapt automatically, but with varying end result intervals.

    With the added code however, all mentioned browsers appeared to settle on about the same apparent speed, and I would think that this would work on any computer capable of executing the actual arrived at interval.

    Comments?
    - John
    ________________________

    Show Additional Thanks: International Rescue Committee - Donate or: The Ocean Conservancy - Donate or: PayPal - Donate

  2. #2
    Join Date
    Jun 2007
    Posts
    543
    Thanks
    3
    Thanked 78 Times in 78 Posts
    Blog Entries
    1

    Default

    wow, i never would of though of that. but instead of including this in scripts, i could see the as a debugger or perfecter to fix the timing in scripts.
    [Jasme Library (Javascript Motion Effects)] My Site
    /\/\@ /\/\@|{
    There are 10 kinds of people in the world, those that understand binary and those that don't.

  3. #3
    Join Date
    Mar 2005
    Location
    SE PA USA
    Posts
    30,495
    Thanks
    82
    Thanked 3,449 Times in 3,410 Posts
    Blog Entries
    12

    Default

    I was thinking that too. However, since I cannot test on every computer, it might be best just to use the code as part of your script. That way each computer could (at least theoretically) arrive at the correct number for the timeout interval for any particular browser it is running. As I said, the execution load is very small and transient (ends after a short time).
    - John
    ________________________

    Show Additional Thanks: International Rescue Committee - Donate or: The Ocean Conservancy - Donate or: PayPal - Donate

  4. #4
    Join Date
    Mar 2005
    Location
    SE PA USA
    Posts
    30,495
    Thanks
    82
    Thanked 3,449 Times in 3,410 Posts
    Blog Entries
    12

    Default

    Update -

    I've been playing around with this idea, and as I suspected (but did not mention) might be the case, it appears that the positive results I got initially were more of a coincidence than anything else. For one thing, to be valid under the circumstances described, I would have to average the unv results, rather than the abstime.ms ones as my code was doing. This new approach is better, but still not ideal. Browsers will still present at various speeds, but it does get them closer into alignment speed wise with each other. However, 1000 (rather than 100) iterations or so seems to be required. This is still a relatively low load execution wise though.
    - John
    ________________________

    Show Additional Thanks: International Rescue Committee - Donate or: The Ocean Conservancy - Donate or: PayPal - Donate

  5. #5
    Join Date
    Jun 2007
    Posts
    543
    Thanks
    3
    Thanked 78 Times in 78 Posts
    Blog Entries
    1

    Default

    i think you should submit this to Submit a DHTML or CSS code.
    [Jasme Library (Javascript Motion Effects)] My Site
    /\/\@ /\/\@|{
    There are 10 kinds of people in the world, those that understand binary and those that don't.

  6. #6
    Join Date
    Jul 2006
    Location
    just north of Boston, MA
    Posts
    1,806
    Thanks
    13
    Thanked 72 Times in 72 Posts

    Default

    or just update the script?

  7. #7
    Join Date
    Mar 2005
    Location
    SE PA USA
    Posts
    30,495
    Thanks
    82
    Thanked 3,449 Times in 3,410 Posts
    Blog Entries
    12

    Default

    After playing around with both the abstime and the Circle Text Trail code for quite a bit now, I've decided that abstime isn't really all that workable. It introduces changes in the timeout interval that can make slower browsers appear about as fast as as faster ones, but this can introduce jerkiness.

    The differences in speed aren't really all that great anyway without abstime, annoying only to folks who view the script in several different browsers expecting it to be the same speed in all of them.

    I'm considering submitting my latest updated version of Circle Text Trail anyway though (without abstime), because it has several improvements over the original. It's more configurable, now uses DOM level 2 to make the trail, exposes no global variables, follows the cursor even on wide pages, and works in modern browsers with or without a valid URL DOCTYPE.
    - John
    ________________________

    Show Additional Thanks: International Rescue Committee - Donate or: The Ocean Conservancy - Donate or: PayPal - Donate

  8. #8
    Join Date
    Jun 2008
    Posts
    589
    Thanks
    13
    Thanked 54 Times in 54 Posts
    Blog Entries
    1

    Default

    Quote Originally Posted by jscheuer1 View Post
    Ever notice how in scripts where you do something like (snippet based loosely upon my updated version of Circling text trail script originally by Tim Tilton):

    Code:
    function drag(){
     y[0] = Math.round(Y[0] += ((ymouse) - Y[0]) * speed);
     x[0] = Math.round(X[0] += ((xmouse) - X[0]) * speed);
     for (var i = n; i > 0; --i){
      y[i] = Math.round(Y[i] += (y[i-1] - Y[i]) * speed);
      x[i] = Math.round(X[i] += (x[i-1] - X[i]) * speed);
     };
     makecircle();
    setTimeout(drag, 20);
    }
    that different browsers run the code at different speeds?

    Well, I have and it has always bothered me. I got this inspiration though just recently to test the timeout interval against instances of the Date object and to adjust said timeout interval based upon that (actual code snippets):

    Code:
    var n = msg.length - 1, a = Math.round(size * diameter * 0.208333), inv = 20, unv = inv,
    Code:
    drag = function(){ // makes the resistance
    if(abstime.l && abstime.l > 0)
    abstime(abstime.a || false);
     y[0] = Math.round(Y[0] += ((ymouse) - Y[0]) * speed);
     x[0] = Math.round(X[0] += ((xmouse) - X[0]) * speed);
     for (var i = n; i > 0; --i){
      y[i] = Math.round(Y[i] += (y[i-1] - Y[i]) * speed);
      x[i] = Math.round(X[i] += (x[i-1] - X[i]) * speed);
     };
     makecircle();
    setTimeout(drag, unv);
    },
    Code:
    abstime = function(be){
    abstime.l--;
     if(be) abstime.b = new Date();
     else abstime.e = new Date();
     if (abstime.b && abstime.e && abstime.l && abstime.l > 0){
      abstime.ms = Math.abs(abstime.b.valueOf() - abstime.e.valueOf());
      unv = abstime.ms > inv? unv - 1 : abstime.ms < inv? unv + 1 : unv;
      abstime.ar[abstime.ar.length] = abstime.ms;
      }
     else if(abstime.ms) unv = Math.round(eval(abstime.ar.join('+')) / abstime.ar.length);
    abstime.a = !abstime.a;
    };
    
    abstime.l = 100;
    abstime.ar = [];
    What this does for the first 99 or so iterations of the code is test the actual intended timeout interval (inv, 20 in this case) against the actual time elapsed between each execution, and adjust the used timeout interval (unv) up or down to attempt to achieve the intended interval.

    After the 99 or so tries, abstime sets the timeout interval based upon an average of all the tries which were stored in the abstime.ar array, and then stops checking and adjusting things, so it is really a very small addition to the code execution wise.

    I was surprised that this actually worked (got various browsers to perform at the virtually same speed, at least as far as the eye could tell), and even more so that the value arrived at was always about the same (+-1, 23/24, in this case) regardless of browser, and a higher value than I would have expected for any of them except the fastest one.

    What I concluded from this (borne out by testing) was that on my system 20 was too short of a timeout interval, had I just used 23 or 24 to begin with, it would have been just fine without all this extra code. But what about other computers?

    And, with this added code (or simply using 24) the script ran much more smoothly in the browser (FF) where it had been fast and a bit jerky at 20.

    This leads me to believe that the famed jerkiness (for many javascript animation type actions) in FF is a result of it actually trying to adhere to set intervals rather than adapting them to what it can actually do smoothly. IE and others (Safari, Opera) appeared to adapt automatically, but with varying end result intervals.

    With the added code however, all mentioned browsers appeared to settle on about the same apparent speed, and I would think that this would work on any computer capable of executing the actual arrived at interval.

    Comments?
    Awesome. I made my own 'set timout' function that uses the time for setting the timeout as well. I used this:

    Code:
    var clock = Date.now || function() {
    return new Date().getTime();
    };
    
    var set = function(ev,t) {
    var start = clock();
    var end = (start+t);
    var loop;
    
    do {
    loop = clock();
    }while(loop < end);
    
    // I tried eval(), but Twey suggested I not
    setTimeout(ev,0);
    };
    With this said, I have one more comment. It pauses everything else to do this, so it isn't efficient. I like yours better .

    -magicyte

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •