Bringing setTimeout to ECMAScript

Jorge jorge at jorgechamorro.com
Sun Mar 20 09:25:19 PDT 2011


On 20/03/2011, at 16:57, David Bruant wrote:

> Le 20/03/2011 16:04, Jorge a écrit :
>> On 20/03/2011, at 15:18, David Bruant wrote:
>>> Le 20/03/2011 14:33, Jorge Chamorro a écrit :
>>>>> A timer that expires is an event, and I would expect events to be serviced in the order they happen. As when I click twice, I'd expect the first click to be serviced before the second click.
>>>>> 
>>>>> So given 2 timers, expiring at t0 and t1 with t0 < t1, if Date.now() is >= t0 and >= t1, I would expect t0 to be serviced first, yes.
>>>>> 
>>> The difference is that the system can understand what is your expectation as a user when you've clicked twice. Both click are clearly sequenced. For timers, the non-determinism due to the computation time of computea and computeb prevents you from /expecting/ anything.
>> Why ? When you do a setTimeout( f, ms ) you know you are saying "fire this @ t >= Date.now() + ms".(Let's leave aside for now the problems wrt Date.now() / wall clock time).
> I agree that for one timer, there is no problem. Tricky case is if you
> want to enforce a policy on how to deal with several delayed timers
> (let's call it "scheduling policy"). That's where I say that it's not
> possible to pretend expecting anything.
> 
> 
>>> In low-memory environment, if a program does an intensive use of timers, maybe that heuristics on the time the timer firing will take could be used to try to get rid of a maximum of timers as soon as possible to save up memory. I would consider this policy as valid due to environment constraints. 
>>>> And if t0 were === t1, I would also expect them to be serviced in the same order in which they were setup:
>>>> 
>>>> setTimeout( f1, 0 );
>>>> setTimeout( f2, 0 );
>>>> setTimeout( f3, 0 );
>>>> setTimeout( f4, 0 );
>>>> setTimeout( f5, 0 );
>>>> 
>>>> ->
>>>> f1()
>>>> f2()
>>>> f3()
>>>> f4()
>>>> f5()
>>>> 
>>> I think it is very dangerous to use talk about things like t0 === t1 and Date.now() >= t0 (concerned about the "or equal"). If ECMAScript has millisecond as granularity, most systems have microseconds if not nanoseconds. 1ms = 10⁶ns. That's a lot! It leaves a lot of room for interpretation. And even the setTimeout calls aren't instantaneous.
>>> 
>>> Consider (milliseconds in comment):
>>> // 0
>>> setTimeout( f1, 1 );
>>> setTimeout( f2, 0 ); // 1 (millisecond change in the middle of the call)
>>> // 2
>>> // -- decision to make on which timer to fire.
>>> Since the millisecond change happened during the second setTimeout, when is scheduled this second timeout?
>> A setTimeout( f, ms ) should be scheduled to fire at t = Date.now() + ms,so in the example above, both would be scheduled to fire at the same t,
> "both would be scheduled to fire the same t". Who said that? The
> millisecond change is in the middle of the setTimeout call. From the
> external point of view, the second timer is scheduled to be called
> between two milliseconds and you (external point of view, not
> implementor) have no idea which one.
> 
>> but, as f1 was setup before f2, f1 should be called before f2. You can achieve this easily with a stack per target time.
> Your argument is based on the implementor point of view. I agree that
> any policy can be implemented. I do not doubt that. I am just saying
> that you cannot verify it from a script point of view, (and so there is
> no point specifying it).
> 
>> I don't see why "you can't verify your expectation".
> If you think you can verify your expectation, please write ECMAScript
> interoperable test cases that show how to test whether an ECMAScript
> engine is conform to your scheduling policy or not. It will be enough to
> convince me.
> Testing one timer ("When you do a setTimeout( f, ms ) you know you are
> saying "fire this @ t >= Date.now() + ms" ") will not be difficult.
> Testing your scheduling policy is a different story.
> 
> A spec is a contract between an provider (implementor) and a client
> (ECMAScript script writer). If the client has no way to ensure that a
> spec detail has been met, there is no point adding this detail to the
> contract.
> With maybe the exception of Date.now() and Math.random() which are
> convinient but comes with no guarantee whatsoever. Their spec are empty
> (not literally, but close). While you seem to have "expectations" on a
> scheduling algorithm.
> 
> If I am missing something and you can write test cases to enforce
> expectation over a particular scheduling policy, please do so.

In order to know *exactly* the target time (Date.now() +ms) that a given setTimeout() has been scheduled for, setTimeout() would have to return it (it doesn't currently):

function newSetTimeout ( f, ms ) {
  var targetTime= Date.now()+ ms;
  scheduleTimeout(f, targetTime);
  return [ targetTime ];
}

The way it's now, most of the times you can, but *sometimes* you can't tell:

var ms= 50;
var t= Date.now();
setTimeout(f, ms);
if (t === Date.now()) {
  //We know: targetTime === t+ms
}
else {
  //Not sure, it can be t+ms or t+ms+1
}

But honestly, I don't see what your point is.
-- 
Jorge.


More information about the es-discuss mailing list