当前位置: 首页 > news >正文

做画册的国外网站银川网站建设一条龙

做画册的国外网站,银川网站建设一条龙,潍坊做网站张家口,百度推广账号问题陈述 当您深入研究时#xff0c;即使是最基本的问题也会变得很有趣。 今天#xff0c;我想深入研究一下Java时间。 我们将从Java API的最基础知识开始#xff0c;然后逐步降低堆栈#xff1a;通过OpenJDK源代码glibc一直到Linux内核。 我们将研究各种环境下的性能开销即使是最基本的问题也会变得很有趣。 今天我想深入研究一下Java时间。 我们将从Java API的最基础知识开始然后逐步降低堆栈通过OpenJDK源代码glibc一直到Linux内核。 我们将研究各种环境下的性能开销并尝试对结果进行推理。 我们将探索经过时间的度量从某个活动的开始事件到结束事件所经过的时间。 这对于性能改进操作监控和超时执行很有用。 以下伪代码是我们几乎可以在任何代码库中看到的常见用法 START_TIME getCurrentTime() executeAction() ELAPSED_TIME getCurrentTime() - START_TIME 有时它不太明确。 我们可以使用面向方面的编程原则来避免本质上与操作有关的污染我们的业务代码但是它仍然以一种或另一种形式存在。 Java中经过的时间 Java提供了两个用于测量时间的基本原语 System.currentTimeMillis()和System.nanoTime() 。 这两个调用之间有几个区别让我们对其进行分解。 1.起点的稳定性 System.currentTimeMillis()返回自Unix纪元开始1970年1月1日UTC以来的毫秒数。 另一方面 System.nanoTime()返回自过去某个任意点以来的纳秒数。 这立即告诉我们currentTimeMillis()的最佳粒度为1毫秒。 它使得不可能测量任何短于1ms的东西。 currentTimeMillis()使用1970年1月1日UTC作为参考点的事实是好事。 为什么好呢 我们可以比较两个不同的JVM甚至两个不同的计算机返回的currentTimeMillis()值。 为什么不好 当我们的计算机没有同步时间时比较将不会很有用。 典型服务器场中的时钟未完全同步并且始终会有一些差距。 如果我要比较两个不同系统的日志文件这仍然可以接受如果时间戳记不能完全同步则可以。 但是有时这种差距可能导致灾难性的结果例如当将其用于分布式系统中的冲突解决时。 2.时钟单调性 另一个问题是不能保证返回值会单调增加。 这是什么意思 当您连续两次调用currentTimeMillis() 第二个调用返回的值可能小于第一个。 这是违反直觉的并且可能导致无意义的结果例如经过时间为负数。 显然 currentTimeMillis()不是衡量应用程序内部经过时间的好选择。 那nanoTime()呢 System.nanoTime()不使用Unix纪元作为参考点而是过去的一些未指定点。 在执行单个JVM的过程中问题仍然存在仅此而已。 因此甚至比较在同一台计算机上运行的两个不同JVM返回的nanoTime()值也没有意义更不用说在单独的计算机上了。 参考点通常与上一次计算机启动有关但这纯粹是实现细节我们根本不能依赖它。 这样做的好处是即使计算机中的挂钟时间由于某种原因而倒退也不会对nanoTime()产生任何影响。 这就是为什么nanoTime()是一个不错的工具可以测量单个JVM上两个事件之间的经过时间但是我们无法比较两个不同JVM上的时间戳。 Java实现 让我们探讨一下Java中如何实现currentTimeMillis()和nanoTime() 。 我将使用来自OpenJDK 14当前负责人的资源 。 System.currentTimeMillis()是一种本地方法因此我们的Java IDE不会告诉我们它是如何实现的。 这个本地代码看起来更好一些 JVM_LEAF(jlong, JVM_CurrentTimeMillis(JNIEnv *env, jclass ignored)) JVMWrapper( JVM_CurrentTimeMillis ); return os::javaTimeMillis(); JVM_END 我们可以看到这只是委派因为实现因操作系统而异。 这是Linux的实现 jlong os::javaTimeMillis() { timeval time; int status gettimeofday(time, NULL); assert (status ! - 1 , linux error ); return jlong(time.tv_sec) * 1000 jlong(time.tv_usec / 1000 ); } 该代码委托给Posix函数gettimeofday() 。 此函数返回一个简单的结构 struct timeval { time_t tv_sec; /* seconds */ suseconds_t tv_usec; /* microseconds */ }; 该结构包含自该纪元以来的秒数和给定秒数内的微秒数。 currentTimeMillis()的约定将返回自该纪元以来的毫秒数因此它必须进行简单的转换 jlong(time.tv_sec) * 1000 jlong(time.tv_usec / 1000) 函数gettimeofday()由glibc实现它最终会调用Linux内核。 稍后我们将更深入地了解。 让我们看看nanoTime()的实现方式事实并没有太大不同System.nanoTime()也是一种本地方法 public static native long nanoTime(); 和jvm.cpp委托给特定于操作系统的实现 JVM_LEAF(jlong, JVM_NanoTime(JNIEnv *env, jclass ignored)) JVMWrapper( JVM_NanoTime ); return os::javaTimeNanos(); JVM_END javaTimeNanos的Linux实现非常有趣 jlong os::javaTimeNanos() { if (os::supports_monotonic_clock()) { struct timespec tp; int status os::Posix::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; } } 有两个分支如果操作系统支持单调时钟它将使用它否则它将委托给我们的老朋友gettimeofday() 。 Gettimeofday()与Posix调用的System.currentTimeMillis()相同 显然随着nanoTime()粒度更高转换看起来有些不同但这是相同的Posix调用 这意味着在某些情况下 System.nanoTime()使用Unix纪元作为参考因此它可以回到过去 换句话说它不能保证是单调的 好消息是据我所知所有现代Linux发行版都支持单调时钟。 我认为该分支是为了与早期版本的kernel / glibc兼容。 如果您对HotSpot如何检测操作系统是否支持单调时钟的详细信息感兴趣请参见此代码 。 对我们大多数人来说重要的是要知道OpenJDK实际上总是调用Posix函数clock_gettime() 该函数在glibc和Linux内核的glibc委托中实现。 基准I –本地笔记本电脑 至此我们对如何实现nanoTime()和currentTimeMillis()有了一些直觉。 让我们看看他们是快闪还是慢速。 这是一个简单的JMH基准 BenchmarkMode (Mode.AverageTime) OutputTimeUnit (TimeUnit.NANOSECONDS) public class Bench { Benchmark public long nano() { return System.nanoTime(); } Benchmark public long millis() { return System.currentTimeMillis(); } } 当我在装有Ubuntu 19.10的笔记本电脑上运行此基准测试时得到以下结果 基准测试 模式 碳纳米管 得分了 错误 单位 板凳 平均 25 29.625 ±2.172 ns / op Benchnano 平均 25 25.368 ±0.643 ns / op 每个调用System.currentTimeMillis()大约需要29纳秒而System.nanoTime()大约需要25纳秒。 不好不可怕。 这意味着使用System.nano()测量花费少于几十纳秒的任何东西可能是不明智的因为我们仪器的开销会高于所测量的间隔。 我们还应该避免在紧密的循环中使用nanoTime() 因为延迟会Swift增加。 另一方面使用nanoTime()来衡量例如来自远程服务器的响应时间或昂贵的计算时间似乎是明智的。 基准II – AWS 在便携式计算机上运行基准测试很方便但不是很实用除非您愿意放弃便携式计算机并将其用作应用程序的生产环境。 相反让我们在AWS EC2中运行相同的基准测试。 让我们使用Ubuntu 16.04 LTS启动一台c5.xlarge机器并使用出色的SDKMAN工具安装由AdoptOpenJDK项目上的精湛人员构建的Java 13 板凳板凳 结果如下 基准测试 模式 碳纳米管 得分了 错误 单位 板凳 平均 25 28.467 ±0.034 ns / op Benchnano 平均 25 27.331 ±0.003 ns / op 这几乎与笔记本电脑上的一样还不错。 现在让我们尝试c3.large实例。 它是较老的一代但仍经常使用 基准测试 模式 碳纳米管 得分了 错误 单位 板凳 平均 25 362.491 ±0.072 ns / op Benchnano 平均 25 367.348 ±6.100 ns / op 这看起来一点都不好 c3.large是一个较旧的较小实例因此预计会有所降低但这太多了 currentTimeMillis()和nanoTime()都慢一个数量级。 起初360 ns听起来可能还不错但是请考虑一下要仅测量一次经过时间您需要两次调用。 因此每次测量花费大约0.7μs。 如果您有10个探针测量不同的执行阶段则您的时间为7μs。 透视一下40gbit网卡的往返行程约为10μs。 这意味着向我们的热路径添加一堆探针可能会对延迟产生非常大的影响 一点内核调查 为什么C3实例比笔记本电脑或C5实例慢得多 事实证明这与Linux时钟源有关更重要的是与glibc-kernel接口有关。 我们已经知道每次调用nanoTime()或currentTimeMillis()调用OpenJDK中的本地代码该本地代码调用glibc后者又调用Linux内核。 有趣的部分是glibc-Linux内核转换通常当进程调用Linux内核函数也称为syscall时它涉及从用户模式切换到内核模式然后再返回。 此转换是一个相对昂贵的操作涉及许多步骤 将CPU寄存器存储在内核堆栈中 使用实际功能运行内核代码 将结果从内核空间复制到用户空间 从内核堆栈恢复CPU寄存器 跳回用户代码 这从来都不是便宜的操作并且随着边信道安全攻击和相关缓解技术的出现它变得越来越昂贵。 对性能敏感的应用程序通常会尽力避免用户到内核的转换。 Linux内核本身提供了一些非常频繁的系统调用的捷径称为vDSO –虚拟动态共享对象 。 它实质上导出了一些功能并将它们映射到进程的地址空间。 用户进程可以调用这些函数就像它们是普通共享库中的常规函数​​一样。 结果 clock_gettime()和gettimeofday()都实现了这样的快捷方式因此当glibc调用clock_gettime() 它实际上只是跳转到内存地址而无需执行昂贵的用户到内核转换。 所有这些听起来像是一个有趣的理论但是并不能解释为什么System.nanoTime()在c3实例上这么慢。 实验时间 我们将使用另一个出色的Linux工具来监视系统调用的数量 perf 。 我们可以做的最简单的测试是启动基准测试并计算操作系统中的所有系统调用。 perf语法很简单 sudo perf stat -e raw_syscalls:sys_enter -I 1000 -a 这将为我们提供每秒的系统调用总数。 一个重要的细节它将仅向我们提供真正的系统调用以及完整的用户模式-内核模式转换。 vDSO调用不计在内。 这是在c5实例上运行时的外观 板凳 您可以看到每秒大约有130个系统调用。 鉴于我们基准测试的每次迭代都少于30 ns因此很明显该应用程序使用vDSO绕过了系统调用。 这是在c3实例上的外观 板凳 每秒超过1,300,000个系统调用 同样 nanoTime()和currentTimeMillis()的延迟也大约翻了一番达到700ns /操作。 这是一个相当有力的指示每个基准测试迭代都会调用一个真实的系统调用 让我们使用另一个perf命令来收集其他证据。 此命令将计算5秒钟内调用的所有系统调用并按名称分组 sudo perf stat -e syscalls:sys_enter_* -a sleep 5 在c5实例上运行时没有任何异常情况。 但是在c3实例上运行时我们可以看到以下内容 板凳 这是我们的吸烟枪 非常有力的证据表明当基准测试在c3框上运行时它将进行真正的gettimeofday()系统调用 但为什么 这是 4.4内核在Ubuntu 16.04中使用 的相关部分 板凳 当Java调用System.currentTimeMillis()时它是映射到用户内存并由glibc调用的函数。 它调用do_realtime() 该struct tv使用当前时间填充struct tv 然后返回给调用者。 重要的是所有这些操作都在用户模式下执行而没有任何缓慢的系统调用。 好吧除非do_realtime()返回VCLOCK_NONE 。 在这种情况下它将调用vdso_fallback_gtod() 这将执行缓慢的系统调用。 为什么c3实例进行回退做系统调用而c5不做 好吧这与虚拟化技术的变化有关 自成立以来AWS一直在使用Xen虚拟化 。 大约2年前 他们宣布从Xen过渡到KVM虚拟化 。 C3实例使用Xen虚拟化较新的c5实例使用KVM。 对我们而言重要的是每种技术都使用Linux Clock的不同实现。 Linux在/sys/devices/system/clocksource/clocksource0/current_clocksource显示当前时钟源。 这是c3 板凳 这是c5 板凳 原来KVM-时钟实现套vclock_mode到VCLOCK_PVCLOCK这意味着慢回退分支以上不采取。 Xen时钟源根本没有设置此模式 而是停留在VCLOCK_NONE 。 这将导致跳入vdso_fallback_gtod()函数该函数最终将启动实际的系统调用 板凳 关于Linux的好处是它具有高度的可配置性并且经常给我们足够的绳索来吊死自己。 我们可以尝试更改c3上的时钟源并重新运行基准测试。 可通过$ cat /sys/devices/system/clocksource/clocksource0/available_clocksource xen tsc hpet acpi_pm $ cat /sys/devices/system/clocksource/clocksource0/available_clocksource xen tsc hpet acpi_pm TSC代表时间戳记计数器 它是一种非常快速的来源并且对我们而言重要的是适当的vDSO实施。 让我们将c3实例中的时钟源从Xen切换到TSC 板凳 检查它是否真的被切换 板凳 看起来不错 现在我们可以重新运行基准测试 基准测试 模式 碳纳米管 得分了 错误 单位 板凳 平均 25 25.558 ±0.070 ns / op Benchnano 平均 25 24.101 ±0.037 ns / op 数字看起来不错 实际上比具有kvm-clock的c5实例更好。 每秒系统调用数与c5实例处于同一级别 板凳 有些人甚至在使用Xen虚拟化时也建议将时钟源切换为TSC。 我对它可能产生的副作用知之甚少但是显然即使是一些大公司也在生产中做到了这一点。 显然这并不证明它是安全的但这表明它对某些人有效。 最后的话 我们已经看到了底层实现细节如何对普通Java调用的性能产生重大影响。 这不仅仅是在微基准测试中可见的理论问题 实际系统也会受到影响 。 您可以直接在Linux内核源代码树中阅读有关vDSO的更多信息。 没有我在Hazelcast的出色同事我将无法进行调查。 这是一支世界一流的团队我从他们那里学到了很多东西 我要感谢布伦丹·格雷格Brendan Gregg收集的各种技巧 我的记忆力一直很差布伦丹创造了一个出色的备忘单。 最后但并非最不重要的一点如果您对性能运行时或分布式系统感兴趣请关注我 翻译自: https://www.javacodegeeks.com/2019/12/measuring-time-from-java-to-kernel-and-back.html
http://www.zqtcl.cn/news/652719/

相关文章:

  • 先建设网站后付款网站相对路径和绝对路径
  • 临沂外贸国际网站建设网站开发外包公司合同
  • 网站设置快捷方式温州网站建设方案报价
  • 经营网站需要什么费用如何鉴赏网站论文
  • 聊城网站推广公司网站 防攻击
  • 小米盒子做网站一个县城广告公司利润
  • 天津市区县档案部门网站建设指导意见网站开发的需求分析教学视频
  • 网站服务合同范本企业网站建设费是无形资产吗
  • 国外做家纺的网站试用体验网站
  • 百度网站下载安装免费制作短视频的软件
  • 山西省这房和城乡建设厅网站邯郸北京网站建设
  • 廊坊网站seo服务主机服务器网站 怎么做
  • 网站的建设与运维东营会计信息网
  • 郑州网站建设程序3g手机网站
  • 建设监理网站设计了网站首页
  • 织梦教育网站开发商务网站建设实训总结
  • 广西执业药师培训网站网站设计 原型图
  • 网站建设客户群体分析微信开放平台小程序开发文档
  • led网站建设wordpress .htaccess 固定链接
  • 学校网站建设申请报告一个好网站设计
  • 网站雪花特效wordpress文件解析
  • 招聘网站哪个好用淮北之窗
  • 索莱宝做网站网站在线布局
  • 站内seo的技巧做php网站阿里云服务器
  • 网站开发需要用到哪些软件爱站网权重查询
  • 免费注册个人网站铁路工程造价信息网
  • 电子商务大型网站建设电商静态网页模板
  • 网站建设公司利润怎么样长沙网站制作作
  • 淄博优化网站企业营销型网站做的好
  • 玉泉营网站建设网络营销公司组织架构