¿Mejor forma de ganar tiempo en milisegundos en javascript?

141

¿Existe una alternativa en JavaScript para obtener tiempo en milisegundos usando el objeto de fecha, o al menos una forma de reutilizar ese objeto, sin tener que crear una instancia de un nuevo objeto cada vez que necesito obtener este valor? Pregunto esto porque estoy tratando de hacer un motor de juego simple en JavaScript, y al calcular el "tiempo de fotograma delta", tengo que crear un nuevo objeto Date en cada fotograma. Si bien no estoy demasiado preocupado por las implicaciones de rendimiento de esto, estoy teniendo algunos problemas con la confiabilidad del tiempo exacto devuelto por este objeto.

Recibo algunos "saltos" extraños en la animación, cada segundo más o menos, y no estoy seguro de si esto está relacionado con la Recolección de Basura de JavaScript o una limitación del objeto Fecha cuando se actualiza tan rápido. Si establezco el valor delta en alguna constante, entonces la animación es perfectamente fluida, así que estoy bastante seguro de que este "salto" está relacionado con la forma en que obtengo el tiempo.

El único código relevante que puedo dar es la forma en que calculo el tiempo delta:

prevTime = curTime;
curTime = (new Date()).getTime();
deltaTime = curTime - prevTime;

Al calcular el movimiento / animación, multiplico un valor constante con el tiempo delta.

Si no hay forma de evitar obtener el tiempo en milisegundos usando el objeto Fecha, sería una función que incremente una variable (que es el tiempo transcurrido en milisegundos desde que comenzó el juego), y que se llama usando la función SetTimer a una velocidad de una vez cada milisegundo sea una alternativa eficiente y confiable?

Editar: he probado mi código ahora en diferentes navegadores y parece que este "salto" en realidad solo es aparente en Chrome, no en Firefox. Pero aún sería bueno si hubiera un método que funcionara en ambos navegadores.

Colin Dumitru
fuente
55
Un objeto por cuadro no
CodesInChaos
2
Sobre la animación que salta cada segundo, ¿podría esto tener algo que ver con el hecho de que Date.getMillisecondssolo devuelve los milisegundos en el segundo actual, es decir, de 0 a 999? No está utilizando esta función en su ejemplo, pero ¿tal vez se está utilizando en otro lugar o en una rama diferente?
Dan Ross
2
¿El salto está relacionado con algunos problemas extraños de resolución en milisegundos? De los documentos de Mozilla : "Al usar now () para crear marcas de tiempo o ID únicos, tenga en cuenta que la resolución puede ser de 15 milisegundos en Windows". ¿Podría estar relacionado con el hipo?
zashu
1
@zashu esto fue hace mucho tiempo, así que no recuerdo ningún detalle para este ejemplo. Pero para una aplicación más reciente, cuando uso Date.now () no veo más saltos.
Colin Dumitru

Respuestas:

173

Prueba Date.now () .

La omisión probablemente se deba a la recolección de basura. Por lo general, la recolección de basura se puede evitar reutilizando las variables tanto como sea posible, pero no puedo decir específicamente qué métodos puede usar para reducir las pausas de recolección de basura.

Joeri Sebrechts
fuente
1
He intentado usar Date.now (), pero todavía tengo los mismos saltos. Así que ahora estoy bastante seguro de que no es un problema con la recolección de basura, sino una limitación al obtener valores exactos con el objeto Date. Como dije, reemplazar el tiempo delta con un valor constante da como resultado animaciones / transiciones suaves, por lo que la única recolección de basura que podría estar ocurriendo es con "nueva Fecha" o "Fecha.ahora ()" (si esta función instancia sus propios objetos que No sé sobre)
Colin Dumitru
22
Solo un aviso: esto no funciona en IE8 y versiones anteriores
Nick
1
Lo hago: / Todo lo que quiero es la fecha en ms. Parece muy complicado para algo tan necesario.
Damien Golding
55
@Prozi +1 .. IE realmente apesta, cuando estoy en la programación web realmente no me importa IE, solo Chrome y
Firefox
3
@TechLife También deberías pensar en los navegadores Android, Safari y Opera, pero estoy de acuerdo en que IE es un montón de basura. Quiero decir que es tan malo que MS se haya rendido y esté implementando un nuevo navegador en W10
Dendromaniac
49

Sé que este es un hilo bastante antiguo, pero para mantener las cosas actualizadas y más relevantes, puede usar la performance.now()funcionalidad más precisa para obtener una sincronización de grano más fina en javascript.

window.performance = window.performance || {};
performance.now = (function() {
    return performance.now       ||
        performance.mozNow    ||
        performance.msNow     ||
        performance.oNow      ||
        performance.webkitNow ||            
        Date.now  /*none found - fallback to browser default */
})();
Chris GW Green
fuente
2
La última alternativa debería ser simplemente en Date.nowlugar de una expresión de función anónima
Bergi
1
Tampoco funciona en navegadores viejos estúpidos, desafortunadamente. Afortunadamente, he convencido a mis clientes de que me paguen por el tiempo que pierdo apoyando IE7 e IE8.
Michael Scheper
2
|| function () {return new Date (). getTime ()}
mmm
2
Vale la pena señalar que performance.now()da tiempo monótono, a diferencia del tiempo de Date. Significa que cada llamada posterior está garantizada para devolver un valor no menor que el anterior.
usuario
48

Hasta donde sé, solo puedes tener tiempo con Date .

Date.now es la solución, pero no está disponible en todas partes: https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Date/now .

var currentTime = +new Date();

Esto le da la hora actual en milisegundos.

Por tus saltos . Si calcula las interpolaciones correctamente de acuerdo con el tiempo del cuadro delta y no tiene algún error de número de redondeo , apuesto por el recolector de basura (GC).

Si hay muchos objetos temporales creados en su ciclo, la recolección de basura tiene que bloquear el hilo para hacer una limpieza y reorganización de la memoria.

Con Chrome, puede ver cuánto tiempo pasa el GC en el panel Línea de tiempo .

EDITAR: desde mi respuesta, Date.now()debería considerarse como la mejor opción, ya que es compatible en todas partes y en IE> = 9.

ngryman
fuente
44
¿Qué función tiene el +saque en +new?
Andrew Scagnelli
33
El +simplemente echados Datea Number, dando una indicación de la hora estándar de UNIX en milisegundos. Usted puede obtener este valor de forma explícita llamando(new Date()).getTime()
ngryman
9
@mikenelson: No es terrible para mí, esto es obvio cuando sabes cómo funciona la coerción. Dicho esto, Date.now()ahora se prefiere ya que su soporte es lo suficientemente grande ahora.
ngryman
1
Yo prefiero solo +que .getTime()... Es más sencillo y no es necesario memorizar los nombres de funciones
2
@TravisJ ¿Atajo impresionante? Para recuperar un valor numérico que ya está dentro de su computadora, cree un objeto, llame a un operador que prueba un int y desencadena una conversión que llama a una función (valueOf) que llama al método de conversión de clase que llama a una función (getTime) que finalmente recupera el valor Luego, el objeto se abandona a su destino, y después de 1000 iteraciones del bucle, tiene 1000 objetos Date eliminados que requieren recolección de basura colgando allí que de repente se vuelcan todos juntos, y mientras su computadora se retrasa, se pregunta qué está sucediendo. :) ¡Increíble!
FrancescoMM
7

Si tiene un objeto de fecha como

var date = new Date('2017/12/03');

entonces hay un método incorporado en javascript para obtener la fecha en formato de milisegundos que es valueOf ()

date.valueOf(); //1512239400000 in milliseconds format
dilip kumar
fuente
2

Esta es una pregunta muy antigua, pero aún como referencia si otros la están mirando, requestAnimationFrame()es la forma correcta de manejar la animación en los navegadores modernos:

ACTUALIZACIÓN: El enlace de Mozilla muestra cómo hacer esto: no tenía ganas de repetir el texto detrás del enlace;)

LarsKnudsen
fuente
44
¡Bienvenido a Stack Overflow ! Es posible que desee incluir una breve explicación de lo requestAnimationFrameque hace que se detenga este "salto" como se describe en la pregunta. ¡Gracias!
Qantas 94 Heavy
2
Incluso con requestAnimationFrame, no debemos suponer que la velocidad de fotogramas sea la misma en todas las plataformas, por lo que aún debemos verificar la hora actual.
Tom Boutell