2010-10-27 18 views
5

Al usar javascript me di cuenta de esto. Puede utilizar¿Este comportamiento de setInterval implica comportamiento de subprocesamiento múltiple en Javascript?

var i=0; 
var startingTime=new Date().getTime(); 
setInterval("foo()",1); 
function foo() { 
    i+=1; 
    if ($("#foodiv").text()==i) { 
     //we detected a doubled value (parallel execution) 
     $("#repdiv").append("[repetition on "+i+"]"); 
    } 
    $("#foodiv").html(i); 
    $("#timediv").html(Math.floor((new Date().getTime()-startingTime)/1000)); 
} 

pero como he leído y trato a mí mismo no es el momento de 1 ms, que es al menos 10 ms o algo así. De hecho, después de 10 segundos, tengo un valor de i alrededor de 2300/2400, y no de 10000 como se esperaba.

¿Este es el factor de tiempo mínimo posible para el procedimiento? Ciertamente no. Si intento esto:

<html><head> 
<script language="javascript" type="text/javascript" src="jquery-1.4.min.js"></script> 
<script type="text/javascript"> 

var i=0; 
var startingTime=new Date().getTime(); 

setInterval("foo()",1);setInterval("foo()",1);setInterval("foo()",1); 
setInterval("foo()",1);setInterval("foo()",1);setInterval("foo()",1); 
setInterval("foo()",1);setInterval("foo()",1);setInterval("foo()",1); 
setInterval("foo()",1);setInterval("foo()",1);setInterval("foo()",1); 
setInterval("foo()",1);setInterval("foo()",1);setInterval("foo()",1); 
setInterval("foo()",1);setInterval("foo()",1);setInterval("foo()",1); 
setInterval("foo()",1);setInterval("foo()",1);setInterval("foo()",1); 
setInterval("foo()",1);setInterval("foo()",1);setInterval("foo()",1); 

function foo() { 
    i+=1; 
    if ($("#foodiv").text()==i) { 
     //we detected a doubled value (parallel execution) 
     $("#repdiv").append("[repetition on "+i+"]"); 
    } 
    $("#foodiv").html(i); 
    $("#timediv").html(Math.floor((new Date().getTime()-startingTime)/1000)); 

} 
</script> 
</head> 
<body> 
<div id="foodiv"></div> (counter) 
<br/> 
<div id="timediv"></div> (seconds passed) 
<br/> 
<div id="repdiv"></div> 
<br/> 
</body> 
</html> 

El contador va a ir muy rápido, y después de 10 segundos, que tienen un valor de 12.000 !!!!. Eso es para mí inexplicable, porque la llamada no se ejecuta en paralelo (o al menos podríamos tener algunos valores doblados de i para diferentes llamadas, figurando en el div repdiv).

¿Alguien me puede explicar eso? Sé que la CPU está muy estresada por todas esas llamadas, pero al menos acelera las cosas sorprendentemente.

He leído todas sus respuestas y las otras misiones en el foro, y confirmaron mi pensamiento. Pero la verdadera pregunta es ¿Por qué? ¿Por qué establecen el límite en 15 ms cuando puedo hacer múltiples llamadas secuenciales obteniendo un tiempo mucho más bajo? Estoy seguro de que este sistema de devolución de llamada múltiple no es una buena práctica, pero puedo hacerlo, y potencialmente puedo saturar la carga de la CPU.

+5

No veo cómo funciona este código, set interval toma una función como primer argumento, no foo(), debería ser más como setInterval (foo, 1). También le falta algo de finalización) después de su if y anexar –

+0

Además, suponiendo que el código es correcto, los valores parecen incorrectos. Con 12 temporizadores, el contador solo irá 12 veces más rápido, por lo que 600 se convertirán en 7200, no en 150000. Algo me dice que este no es el código que el OP ha probado. – casablanca

+0

tienes razón, edité el código muchas veces y lo recreé en casa, pero el concepto no está cambiando. Voy a repetir las cosas como lo hice de manera efectiva. Además, si notas que omití el código html, y eso empeorará las cosas si pruebas esto tal como está. – mizar

Respuesta

0

El segundo valor pasado al método setInterval es de hecho un valor mínimo. Aunque 1 representa 1 milisegundo y es poco probable que la mayoría de los navegadores le den exactamente este tiempo de espera. Otra respuesta dice que es más probable que sea alrededor de 15 milisegundos.

Aún así, el segundo elemento es un valor mínimo que explica adecuadamente la primera muestra.

La segunda muestra también se explica por este comportamiento. Cada uno de los métodos setInterval que llama registra una devolución de llamada completamente independiente. Cada uno tiene un mínimo de 1 pero no dependen el uno del otro. Por lo tanto, es perfectamente válido para todos disparar dentro del mismo intervalo de 1 milisegundo (siempre que cada uno espere 1 milisegundo antes de volver a disparar).

+0

No tengo ningún navegador compatible con una precisión de 1 ms. Parece ser 15ms para la mayoría de los navegadores :) –

+0

@Vivin, señalado en el primer párrafo. Dejé 1 en el segundo párrafo para tratar de evitar confusiones para el OP. – JaredPar

+0

Ah, no lo vi cuando comencé. No recargó la página. ¡Mi error! –

1

No, JavaScript no tiene multiprocesamiento, al menos no por el momento.

Por favor, lea this answer para ver cómo funciona setInterval.

8

No, Javascript tiene una sola hebra. Cuando ejecuta setInterval o setTimeout, se genera un evento que luego se agrega a la cola de ejecución del navegador. Por lo tanto, aunque no puede garantizar que el código se ejecutará exactamente cuando desee que se ejecute, puede estar seguro de que el evento se generará cada vez que se supone que se generará. Entonces, en este caso, tienes 12 eventos que se están generando muy cerca uno del otro. Noté que usaste 1 como valor de intervalo. Sin embargo, los valores mínimos en la mayoría de los navegadores son alrededor de 15 (ver here para más información.) El navegador ejecutará los eventos en el orden en que están en la cola de ejecución (en setInterval, los eventos intentan ponerse al día. respuesta a la que Marcel se vinculó, para más detalles).

Lo que esto significa es que en el primer escenario tiene un evento generado cada 15 o más milisegundos. Entonces el contador se incrementa más lentamente. Pero en el segundo caso, tiene doce eventos que se disparan bastante cerca el uno del otro cada 15 o menos milisegundos, por lo que el contador aumenta mucho más rápido.

1

El código que usted envió no funciona, aquí está el código corregido:

var i=0; 
setInterval(foo,1); 

function foo() { 
    i+=1; 
    if ($("#foodiv").text()==i) { 
    //we detected a doubled value (parallel execution) 
    $("#repdiv").append("[repetition on "+i+"]"); 
    } 
    $("#foodiv").html(i); 
} 

Si nos fijamos en el rendimiento de la CPU mientras se ejecuta el código, verá que es apenas funciona en absoluto, lo que significa que la tasa más baja no se debe a que el código esté ocupado. Simplemente no disparará el intervalo tantas veces como lo solicite.

(Si se arranca doce intervalos, la carga sigue siendo apenas perceptible. Empecé 200 intervalos antes de conseguir una carga cercana al 100% en uno de los núcleos.)

El navegador utiliza algún tipo de reloj para determinar qué intervalos deben dispararse, y ese reloj generalmente tiene una resolución inferior a milisegundos. Por lo tanto, el intervalo no volverá a dispararse hasta la próxima señal del reloj, que en su caso parece estar a unos 15 ms de diferencia.

Cuestiones relacionadas