JavaScript 是否提供高分辨率计时器?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/6875625/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-23 23:35:09  来源:igfitidea点击:

Does JavaScript provide a high resolution timer?

javascriptanimation

提问by sysrpl

Does JavaScript provide a high resolution timer?

JavaScript 是否提供高分辨率计时器?

I've written a few game engines from scratch, some in C, some in Java, and some in Flash. I always follow the same basic model when it comes to animations and interactive graphics. Create a basic class/structure with the following design:

我从头开始编写了一些游戏引擎,有些是用 C 语言编写的,有些是用 Java 编写的,有些是用 Flash 编写的。在动画和交互式图形方面,我始终遵循相同的基本模型。使用以下设计创建一个基本类/结构:

void init() { /* Called once, preload essential resources here. */ }
void update(double time) { /* Updates game/animation state using high resolution time. */ }
void render(double time) { /* Updates screen graphics using high resolution time. */ }

void run()
{
    double time;
    init();
    while (!done)
    {
        time = queryTime();
        update(time);
        render(time);
    }
}

Time is so important to smooth animations and game state calculations. In native code Windows, I use QueryPerformanceCounter()and QueryPerformanceFrequency()to perform the role of queryTime()in each game loop and pass the time to update/render. In Java, I use System.nanoTime().

时间对于平滑动画和游戏状态计算非常重要。在本机代码 Windows 中,我使用QueryPerformanceCounter()QueryPerformanceFrequency()来执行queryTime()每个游戏循环中的角色,并通过时间来更新/渲染。在 Java 中,我使用System.nanoTime().

What's the equivalent in JavaScript? That is, some function like queryTime()which returns a time value with a high degree of accuracy (sub millisecond). From what I've heard the best accuracy you can get in JavaScript is about 15 ms ... which is horrible for animation.

JavaScript 中的等价物是什么?也就是说,一些函数像queryTime()返回一个高精度(亚毫秒)的时间值。据我所知,您在 JavaScript 中可以获得的最佳准确度约为 15 毫秒……这对于动画来说太可怕了。

采纳答案by mwcz

See @h3r3's answer—it is the correct answer.

请参阅@h3r3 的答案——这是正确的答案。

Milliseconds are the best you can hope for in JavaScript. And, like you said, it isn't very accurate. See Stack Overflow question Microsecond timing in JavaScript.

毫秒是您在 JavaScript 中所能期望的最佳时间。而且,就像你说的,它不是很准确。请参阅 Stack Overflow 问题JavaScript 中的微秒计时

timer.jspurports to provide up to microsecond resolution, but it is only available for Google Chrome.

timer.js声称可以提供高达微秒的分辨率,但它仅适用于Google Chrome

Update: timer.js does notsupport microsecond resolution. It just multiplies millisecond count by 1000.

更新:timer.js并没有支持微秒分辨率。它只是将毫秒计数乘以 1000。

Sorry, there isn't better news!

抱歉,没有更好的消息了!

回答by h3r3

Almost all modern browsers provide a high resolution timer. It's the "High Resolution Time" W3C standard: http://www.w3.org/TR/hr-time/#sec-DOMHighResTimeStamp.

几乎所有现代浏览器都提供高分辨率计时器。这是“高分辨率时间”W3C 标准:http: //www.w3.org/TR/hr-time/#sec-DOMHighResTimeStamp

It allows you to get a sub-millisecond accurate timestamp by calling window.performance.now(). This returns a time stamp in ms, but it is a float so you still get sub-millisecond resolution.

它允许您通过调用window.performance.now()获得亚毫秒级的准确时间戳。这将返回一个以毫秒为单位的时间戳,但它是一个浮点数,因此您仍然可以获得亚毫秒级的分辨率。

Very old browsers may implement a "prefixed" version of this standard, e.g. WebKit based browsers used to implement window.performance.webkitNow()

非常旧的浏览器可能会实现此标准的“带前缀”版本,例如用于实现window.performance.webkitNow() 的基于 WebKit 的浏览器

Here is some code you can use to get the the accurate timestamp when available and fallback to standard precision otherwise:

以下是一些代码,您可以使用它在可用时获取准确的时间戳,否则回退到标准精度:

if (window.performance.now) {
    console.log("Using high performance timer");
    getTimestamp = function() { return window.performance.now(); };
} else {
    if (window.performance.webkitNow) {
        console.log("Using webkit high performance timer");
        getTimestamp = function() { return window.performance.webkitNow(); };
    } else {
        console.log("Using low performance timer");
        getTimestamp = function() { return new Date().getTime(); };
    }
}

getTimestamp();

Note that this getTimestamp()function does not return a value that represents the current date/time. The returned value can only be used to measure time-periods, by subtracting two different timestamps. E.g.

请注意,此getTimestamp()函数不会返回表示当前日期/时间的值。通过减去两个不同的时间戳,返回值只能用于测量时间段。例如

var t1 = getTimestamp();
//... some other code
var t2 = getTimestamp();
console.log("Time delta: " + (t2 - t1));

回答by katspaugh

Instead of while (true)/setInterval, use recursive requestAnimationFrame. It will run smoother than timeout based animations. It provides timestamps if you need your animation to run at slowerpath.

而不是while (true)/ setInterval,使用递归requestAnimationFrame。它将比基于超时的动画运行更流畅。如果您需要动画以较慢的路径运行,它会提供时间戳。

回答by Oleg Kikin

As of now (February 25, 2013), the quality of high-performance times in Chrome 24 is pretty horrible.

截至目前(2013 年 2 月 25 日),Chrome 24 中高性能时代的质量非常糟糕。

var old = 0; 

for (var i=0; i<10; i++) {
    var t = window.performance.now(); 
    var d = t - old; 
    old = t; 
    console.log(t + ' += ' +d); 
}

outputs something like this:

输出是这样的:

609689.000000013 += 609689.000000013
609689.9999999441 += 0.9999999310821295
609689.9999999441 += 0
609689.9999999441 += 0
609689.9999999441 += 0
609690.9999999916 += 1.0000000474974513
609690.9999999916 += 0
609690.9999999916 += 0
609691.9999999227 += 0.9999999310821295
609691.9999999227 += 0

Which shows that

这表明

1) Sampling happens rarely

1) 抽样很少发生

2) The precision is still around 1ms, not in the microsecond range.

2)精度还在1ms左右,不在微秒范围内。

回答by underrun

Because this comes up when searching for JavaScript and high resolution timer, it is worth noting that window.performance.nowis now functional (at least in Google Chrome v. 26) and provides ~microsecond resolution.

因为在搜索 JavaScript 和高分辨率计时器时会出现这种情况,所以值得注意的是,window.performance.now它现在可以正常运行(至少在 Google Chrome v. 26 中)并提供~微秒分辨率。

var d = 0;
var p = window.performance;
for(var i=0; i<10; i++) {
    d = -1 * (p.now() - p.now());
    console.log(d*1000);
}

It gave me this (in microseconds):

它给了我这个(以微秒为单位):

5.0000089686363935
3.9999722503125668
1.00000761449337
1.00000761449337
1.00000761449337
1.9999861251562834
1.9999861251562834
1.00000761449337
1.00000761449337
0.9999785106629133

I ran some stats on a few sets of 10k+ results. Minimum is about 1 microsecond, and the mean is about 1.25 microseconds on my machine (MacBook Air). Occasionally there are high outliers at the 100+ microsecond mark, but there were frequent results above 10 microseconds.

我对几组 10k+ 结果进行了一些统计。最小值约为 1 微秒,我的机器(MacBook Air)上的平均值约为 1.25 微秒。偶尔会在 100+ 微秒标记处出现高异常值,但经常出现超过 10 微秒的结果。

So the high-resolution timer is now capable of timing subtraction at microsecond resolution.

因此,高分辨率计时器现在能够以微秒分辨率进行计时减法。

回答by Fox32

Node.js has a high resolution timer, too.

Node.js 也有一个高分辨率的计时器。

process.hrtime()

See the documentation for details

有关详细信息,请参阅文档

回答by Juan Mendes

Here's what your code should look like in JavaScript, so it doesn't block the user interface and doesn't use window.requestAnimationFramewhich does not work cross-browser.

这是您的代码在 JavaScript 中的样子,因此它不会阻塞用户界面,也不会使用不能跨浏览器工作的window.requestAnimationFrame

/* Called once, preload essential resources here. */
function init() {}

/* Updates game/animation state */
function update(time) {}

/* Updates screen graphics  */
function render(time) {}

window.onload = function()
{
    var time;
    var done = false;

    init();
    // Using setTimeout passing zero makes the animate function run
    // as soon as possible, but yielding first.
    setTimeout(animate, 0);

    function animate () {
        time = new Date();
        update(time);
        render(time);
        if (!done) {
            setTimeout(animate, 0);
        }
    }
}

A problem with this approach is that the animate()may get called more often than the screen gets updated (at 60 Hz it won't update more often than abot every 16 ms), causing extra rendering that never makes it to the screen. That's why you should stick with requestAnimationFrame if possible.

这种方法的一个问题是,animate()调用的频率可能比屏幕更新的频率更高(在 60 Hz 下,它不会比每 16 毫秒更新一次 abot 更频繁),从而导致额外的渲染永远不会出现在屏幕上。这就是为什么你应该尽可能坚持使用 requestAnimationFrame 的原因。

回答by Chiguireitor

You can use CSS 3 transforms for simple animations that will get full hardware acceleration and will run silky smooth on most modern browsers... If you're expecting smooth animations on WebGLyou're pretty much out of luck, because there's no submillisecond precision on JavaScript.

您可以使用CSS 3个变换为简单的动画,将获得完整的硬件加速,能够运行如丝般柔滑上最现代的浏览器?如果你在期待流畅的动画WebGL的你是非常的运气,因为没有亚毫秒精度在 JavaScript 上。

Currently, there's a lot of progress on enabling game related technologies for the web (see for example the mouse lock draft which is being actively developed our the fullscreen API... Maybe you can start the movement for microsecond precision timers in JavaScript ;-)

目前,在为 Web 启用游戏相关技术方面取得了很多进展(例如,请参阅我们正在积极开发我们的全屏API的鼠标锁定草案……也许您可以在 JavaScript 中启动微秒精度计时器的运动;-)

回答by degr

Just now I search for such solution, and found this thread. As I can see, all measurements done incorrect, because nobody know how work console.log function. From my experience (and practice) it take too much time, and even work asynchronously.

刚才我搜索了这样的解决方案,并找到了这个线程。正如我所看到的,所有的测量都不正确,因为没有人知道 console.log 函数是如何工作的。根据我的经验(和实践),它需要太多时间,甚至异步工作。

Just compare this code samples:

只需比较此代码示例:

var old = 0; 

for (var i=0; i<10; i++) {
    var t = window.performance.now(); 
    var d = t - old; 
    old = t; 
    console.log(t + ' += ' +d); 
}

and this

和这个

var old = 0; 
var out = [];
for (var i=0; i<10; i++) {
    var t = window.performance.now(); 
    var d = t - old; 
    old = t; 
    out.push(t + ' += ' +d)
}
console.log(out);

回答by Blacklight

Besides the already provided excellent answers, you may also have a look at marky, a

除了已经提供的优秀答案,您还可以看看marky,一个

high-resolution JavaScript timer based on performance.mark/measure (461 bytes min+gz)

基于 performance.mark/measure 的高分辨率 JavaScript 计时器(461 字节 min+gz)

It also includes dev tools visualizations and is tested in a broad range of browsers.

它还包括开发工具可视化,并在广泛的浏览器中进行了测试。