System.nanoTime()背后是什么?

在Java世界中,对System.nanoTime()的理解非常好。 总有一些人说它是快速,可靠的,并且在可能的情况下,应该使用它代替System.currentTimemillis()进行计时。 总的来说,他绝对是在撒谎,一点也不差,但是开发人员应该意识到一些缺点。 同样,尽管它们有很多共同点,但是这些缺点通常是特定于平台的。

视窗

使用QueryPerformanceCounter API实现功能,众所周知该API存在一些问题。 它可能会飞速发展 ,有人报告说在多处理器计算机上的速度可能非常慢 ,等等。我花了一些时间上网尝试查找QueryPerformanceCounter的工作原理和作用。 关于该主题尚无明确结论,但是有一些帖子可以简要介绍其工作原理。 我会说,最有用的,大概是说和那人。 当然,只要稍作搜索,就能找到更多,但信息大致相同。

因此,如果可用,则实现似乎正在使用HPET 。 如果不是,则它将TSC与CPU之间的值进行某种形式的同步。 有趣的是, QueryPerformanceCounter承诺返回的值将以恒定的频率增加。 这意味着,在使用TSC和多个CPU的情况下,可能不仅会遇到一些困难,不仅因为CPU可能具有不同的TSC值,而且可能具有不同的频率。 请牢记所有注意事项Microsoft 建议使用SetThreadAffinityMask来阻塞将QueryPerformanceCounter调用到单个处理器的线程,这显然不会在JVM中发生。

LINUX

Linux与Windows非常相似,除了它更加透明(我设法下载了源代码:))。 该值从带有CLOCK_MONOTONIC标志的clock_gettime中读取(对于真正的男人,源可从Linux源的vclock_gettime.c中获得)。 使用TSC或HPET 。 与Windows的唯一区别是Linux甚至不尝试同步从不同CPU读取的TSC值,而是按原样返回它。 这意味着该值可以在读取时依赖于CPU的依赖关系上来回跳。 另外,与Windows签约时,Linux不会保持更改频率恒定。 另一方面,它绝对应该提高性能。

索拉里斯

Solaris很简单。 我相信通过gethrtime可以实现与linux差不多相同的clock_gettime实现。 区别在于Solaris保证计数器不会跳回,这在Linux上是可能的,但是有可能返回相同的值。 从源代码可以看出,这种保证是使用CAS实现的,它需要与主存储器同步,并且在多处理器机器上可能相对昂贵。 与Linux相同,更改率可能有所不同。

结论

结论是多云之王。 开发人员必须意识到功能不是完美的,它可以向后或向前跳跃。 它可能不会单调变化,并且变化率会随CPU时钟速度的变化而变化。 而且,它并没有许多人想象的那么快。 在我的Windows 7计算机上进行单线程测试时,它仅比System.currentTimeMillis()快约10%,而在多线程测试中,线程数与CPU数相同,只是相同。 因此,总的来说,它所提供的只是分辨率的提高,这在某些情况下可能很重要。 最后要注意的是,即使CPU频率没有变化,也不要认为您可以将该值可靠地映射到系统时钟,请参见此处的详细信息。

附录

附录包含针对不同操作系统的功能实现。 源代码来自OpenJDK v.7。

的Solaris

// gethrtime can move backwards if read from one cpu and then a different cpu
// getTimeNanos is guaranteed to not move backward on Solaris
inline hrtime_t getTimeNanos() {if (VM_Version::supports_cx8()) {const hrtime_t now = gethrtime();// Use atomic long load since 32-bit x86 uses 2 registers to keep long.const hrtime_t prev = Atomic::load((volatile jlong*)&max_hrtime);if (now <= prev)  return prev;   // same or retrograde time;const hrtime_t obsv = Atomic::cmpxchg(now, (volatile jlong*)&max_hrtime, prev);assert(obsv >= prev, "invariant");   // Monotonicity// If the CAS succeeded then we're done and return "now".// If the CAS failed and the observed value "obs" is >= now then// we should return "obs".  If the CAS failed and now > obs > prv then// some other thread raced this thread and installed a new value, in which case// we could either (a) retry the entire operation, (b) retry trying to install now// or (c) just return obs.  We use (c).   No loop is required although in some cases// we might discard a higher "now" value in deference to a slightly lower but freshly// installed obs value.   That's entirely benign -- it admits no new orderings compared// to (a) or (b) -- and greatly reduces coherence traffic.// We might also condition (c) on the magnitude of the delta between obs and now.// Avoiding excessive CAS operations to hot RW locations is critical.// See http://blogs.sun.com/dave/entry/cas_and_cache_trivia_invalidatereturn (prev == obsv) ? now : obsv ;} else {return oldgetTimeNanos();}
}

的Linux

jlong os::javaTimeNanos() {if (Linux::supports_monotonic_clock()) {struct timespec tp;int status = Linux::clock_gettime(CLOCK_MONOTONIC, &tp);assert(status == 0, "gettime error");jlong result = jlong(tp.tv_sec) * (1000 * 1000 * 1000) + jlong(tp.tv_nsec);return result;} else {timeval time;int status = gettimeofday(&time, NULL);assert(status != -1, "linux error");jlong usecs = jlong(time.tv_sec) * (1000 * 1000) + jlong(time.tv_usec);return 1000 * usecs;}
}

视窗

jlong os::javaTimeNanos() {if (!has_performance_count) {return javaTimeMillis() * NANOS_PER_MILLISEC; // the best we can do.} else {LARGE_INTEGER current_count;QueryPerformanceCounter(¤t_count);double current = as_long(current_count);double freq = performance_frequency;jlong time = (jlong)((current/freq) * NANOS_PER_SEC);return time;}
}

参考:

  • System.nanoTime()背后是什么? 来自我们的JCG合作伙伴   Stas博客上的 Stanislav Kobylansky。
  • 热点虚拟机内部:时钟,计时器和计划事件
  • 当心QueryPerformanceCounter()
  • 为Windows实施持续更新的高分辨率时间提供程序
  • 游戏计时和多核处理器
  • 高精度事件计时器(维基百科)
  • 时间戳计数器(维基百科)

翻译自: https://www.javacodegeeks.com/2012/02/what-is-behind-systemnanotime.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/373322.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

python连接SQL Server取多个结果集:Pymssql模块

基本的用法可以参考&#xff1a;python连接SQL Server&#xff1a;Pymssql模块 和上一篇文章中的代码&#xff0c;只取一个结果集不同&#xff0c;这次会一次运行2个sql语句&#xff0c;然后分别取出2个结果集&#xff0c;打印输出。 代码中有详细的注释&#xff0c;一看就明白…

状态不属于代码

Web应用程序中的“状态”是什么&#xff1f; 它就是要存储的数据&#xff08;无论目的地是什么—内存&#xff0c;数据库&#xff0c;文件系统&#xff09;。 应用程序本身不得在代码中存储任何状态。 这意味着您的类应仅包含带有无状态对象的字段。 换句话说&#xff0c;在程序…

Xen安全架构sHype/ACM策略配置图文教程

实验要求 1. 熟悉Xen虚拟化平台部署&#xff1b; 2. Xen sHype/ACM安全架构中的Simple TE和Chinese Wall策略及事实上现机制的分析与验证。 第1章 Xen环境部署 1.1 版本号选择 因为Ubuntu使用广泛。软件包易于下载。我们选择Ubuntu系统进行Xen部署…

Python 辨异 —— __init__ 与 __new__

__init__ 更多的作用是初始化属性&#xff0c;__new__ 进行的是创建对象&#xff0c;显然 __new__ 要早于 __init__ 发生。 考虑一个继承自 tuple 的类&#xff0c;显然在 __init__ 无法对其成员进行修改&#xff1b; class Edge(tuple):def __new__(cls, e1, e2):return tuple…

java弹出虚拟键盘_JS实现电脑虚拟键盘的操作

本文实例为大家分享了JS实现电脑虚拟键盘的具体代码&#xff0c;供大家参考&#xff0c;具体内容如下需求&#xff1a;1.当输入框光标聚焦时&#xff0c;电脑虚拟键盘弹出2.在输入框输入内容时&#xff0c;键盘跟着变化具体实现代码如下&#xff1a;Html部分&#xff1a;电脑键…

Apache Mahout:入门

最近&#xff0c;我有一个有趣的问题要解决&#xff1a;如何使用自动化对不同来源的文本进行分类&#xff1f; 前一段时间&#xff0c;我读到一个有关该项目以及许多其他文本分析工作的项目– Apache Mahout 。 尽管它不是一个非常成熟的版本&#xff08;当前版本为0.4 &#x…

Javascript中最常用的55个经典技巧(转)

1. οncοntextmenu"window.event.returnValuefalse" 将彻底屏蔽鼠标右键 <table border οncοntextmenureturn(false)><td>no</table> 可用于Table 2. <body onselectstart"return false"> 取消选取、防止复制 3. οnpaste"…

向数组添加元素 java_java如何向数组里添加元素

向数组里添加一个元素怎么添加&#xff0c;这儿总结有三种方法&#xff1a;1、一般数组是不能添加元素的&#xff0c;因为他们在初始化时就已定好长度了&#xff0c;不能改变长度。但有个可以改变大小的数组为ArrayList&#xff0c;即可以定义一个ArrayList数组&#xff0c;然后…

JBoss Drools –入门

这篇文章是关于我如何掌握JBoss Drools的 。 其背后的原因是&#xff1a;SAP收购了我公司当前的规则引擎&#xff0c;而Drools是我们将寻找的另一种选择&#xff0c;只要有人掌握了概念验证的技能即可。 尽管似乎有大量的文档&#xff0c;但是我总是会通过示例来发现它是有帮助…

android使用bintray发布aar到jcenter

前言 这两天心血来潮突然想把自己的android library的aar放到jcenter里面&#xff0c;这样一来自己便可以在任何时间任何地点通过internet得到自己的library的引用了&#xff0c;况且现在android studio已经默认使用jcenter的repositories作为依赖来源&#xff0c;以前的mavenc…

Java不是文明语言吗?

几周前&#xff0c;我有机会学习iOS编程。 我的老板认为我更像是“计算机科学家”&#xff0c;而不是开发人员&#xff0c;这意味着我可以将自己的知识应用于开发一两个iPad应用程序–我要做的就是学习Objective-C&#xff0c; iOS SDK&#xff1a;到底有多难&#xff1f; 尽管…

PHP 进程详解

PHP 进程详解PHP 进程详解 如下内容从《操作系统精髓与设计原理》中总结提炼得出&#xff0c;删除了大部分对于理解进程有干扰的文字&#xff0c;对进程知识结构进行的梳理。几乎所有内容为按照书本上摘抄下来的&#xff0c;我目前还总结提炼不出像作者这么深刻的见解。那么就先…

35. Search Insert Position

public class Solution {public int searchInsert(int[] nums, int target) {int lennums.length;int i0;for(;i<len;i){if(nums[i]>target)break;}return i;} } 转载于:https://www.cnblogs.com/aguai1992/p/5351442.html

MySQL 后from多个表_MYSQL回顾(多表查询相关)

前言简单的数据我们可以直接从一个表中获取&#xff0c;但在真实的项目中查询符合条件的数据通常需要牵扯到多张表&#xff0c;这就不得不使用多表查询。多表查询分为多表连接查询、符合条件链接查询、子查询。多表连接查询包括内连接、外连接、全连接。符合条件连接查询本质上…

玩! 框架+ Google Guice

在我目前正在工作的项目中&#xff0c;我们开始使用Google Guice。 对于那些不知道的人&#xff0c; Google Guice是一个依赖项注入框架。 依赖项注入背后的基本思想是提供一个它依赖的类&#xff0c;而不是使依赖类负责实例化它所依赖的对象。 Play具有用于整合Guice的模块&am…

java都要caps标点_第 1 章 管理 Java CAPS 用户

第 1 章 管理 Java CAPS 用户在此处列出的主题提供了有关如何管理 Sun JavaTM Composite Application Platform Suite (Java CAPS) 中的用户的信息。如果您有任何问题&#xff0c;请参见 http://goldstar.stc.com/ 中的 Java CAPS Web 站点。管理系统信息库用户此类别包含以下用…

基于OpenCV 的美颜相机推送直播流

程序流程&#xff1a; 1.图像采集 先从opencv&#xff08;2.4.10版本&#xff09;采集回来摄像头的图像&#xff0c;是一帧一帧的 每一帧图像是一个矩阵&#xff0c;opencv中的mat 数据结构。 2.人脸的美化 人脸美化&#xff0c;我们用的皮肤检测&#xff0c;皮肤在颜色空间是特…

Linux驱动开发常用头文件

头文件目录中总共有32个.h头文件。其中主目录下有13个&#xff0c;asm子目录中有4个&#xff0c;linux子目录中有10个&#xff0c;sys子目录中有5个。这些头文件各自的功能如下&#xff1a; 1、主目录 <a.out.h>&#xff1a;a.out头文件&#xff0c;定义了a.out执行文件格…

Spring线程池服务

线程池对于执行同步和异步过程非常重要。 本文介绍如何使用Spring开发和监视线程池服务。 创建线程池已通过两种替代方法进行了说明。 二手技术 &#xff1a; JDK 1.6.0_21 Spring3.0.5 Maven的3.0.2 步骤1&#xff1a;建立已完成的专案 创建一个Maven项目&#xff0c;如下…

我的世界java村民繁殖_我的世界:Java19w08a更新,村民加强守卫,小狐狸背叛

虽然这句话很绕口&#xff0c;其实意思很简单&#xff0c;那就是之前的隐身药水没有什么用&#xff0c;该被打还是被打。因为这个可是害惨了流浪商人&#xff0c;不过这次好了&#xff0c;流浪商人在喝了隐身药水之后就能安全度过晚上了。NO.3 皮革马铠马铠是属于马的盔甲&…