通过 RDTSC 指令从 CPU 寄存器中直接获取系统时钟
很多时候我们使用函数 gettimeofday
以及 clock_gettime
作为我们获取 wall lock的时钟函数。
因为这两种函数是 glibc 提供的用户封装,简单易用,而且能够精确到 ns,对于大多数的时钟需求场景都已经够用了。
但是如果 我们的应用 调用时钟频繁 且 对 多线程场景下时钟的单调性要求不是特别高的时候 ,以上提到的两个 glibc 函数的开销其实是有点大的。
gettimeofday
底层是会调用到系统调用sys_gettimeofday
,执行逻辑会陷入内核,将内核保存的 walllock 和 jiffies 做一个综合的精度计算,将计算结果从内核态拷贝到用户态,交给timeval,这整个过程可以说开销是比较大的。(需要系统调用)clock_gettime
,这个函数同样的需要执行一个系统调用 ,并且做 精度处理之后才返回给用户态。
举个例子,我们分布式系统中的打点系统可以说非常重要,事关整个系统健康情况的展示,能够帮助我们提前或者及时得准确发现系统中潜在的问题, 但是因为这一些打点需要在关键路径上,往往对整个系统性能会有一定的损耗。而这一些打点 并不影响整个分布式系统中 为分布式事务选择的时钟(可以用两套时钟),只需要能够计算出一个操作前后的时间差即可,保持单线程内的单调性即可。
所以,如果我们的系统中所有的时钟都采用 glibc 实现的两种方式,对于频繁的打点系统来说 代价实在是有点大,而且对关键路径的性能都会有一定的影响。
今天介绍一个可以从 CPU 寄存器中直接获取 walllock 的汇编指令 RDTSC
。
我们目前大多数的服务器系统是 AMD64 , x86_32/x86_64 位,可以通过如下 代码获取:
#include <stdio.h>
#include <inttypes.h>int main() {uint64_t a,d,t;__asm__ volatile("rdtsc" : "=a"(a), "=d"(d));t = ((d << 32) | a);printf("%lu\n",t);return 0;
}
拿到的 walllock 是 自1970.1.1 到现在 的CPU周期数,对于 GHZ 的CPU 来说单位就是ns。
我们的服务器主板有一个即使机器断电重启也不会重设的存储单元 RTC,它会将当前机器到 1970.1.1 经过的时间转化为当前机器的CPU时钟周期并存储下来。
我们的CPU 在完成一个时钟周期之后会在 MSR(model-specific register) 寄存器中存储计数(64位),我们的 RDTSC (read Time-Stamp Counter) 指令就是直接从 MSR 寄存器中取出计数信息,其中的 高32位 放在 edx 寄存器中,低 32位放在eax 寄存器中。
这也就是为什么 我们在AMD64 下执行这个指令需要在取到结果之后对存储高 32位数据 的 d
变量做一个移位。
这样我们就可以完整得实现一个 在AMD64 架构下的 rdtsc 指令的时间统计:
#include <stdio.h>
#include <inttypes.h>static inline
uint64_t rdtsc_time() {uint64_t a,d;__asm__ volatile("rdtsc" : "=a"(a), "=d"(d));return ((d << 32) | a);
}static inline
uint64_t clock_to_nsec(uint64_t begin, uint64_t end) {double clock_diff;// 这里做一些简单的单调性处理, 防止 end < begin.if (end < begin)return (0);clock_diff = (double)(end - begin);return ((uint64_t)(clock_diff);
}int main() {uint64_t start_ns = rdtsc_time();// do some code......uint64_t end_ns = rdtsc_time();fprintf(stdout, "code execute time(ns) : %lu\n", clock_to_nsec(start_ns, end_ns));return 0;
}
为了兼容不同的平台,像 i386 以及 arm 平台,所以,我们需要变更 rdtsc_time 函数为如下形态(不同架构下的获取时钟指令有一些差异):
static inline uint64_t
rdtsc_time(void)
{
#if defined(__i386) // intel 80386 架构{uint64_t x;__asm__ volatile("rdtsc" : "=A"(x));return (x);}
#elif defined(__amd64) // amd x86_64架构{uint64_t a, d;__asm__ volatile("rdtsc" : "=a"(a), "=d"(d));return ((d << 32) | a);}
#elif defined(__aarch64__) // arm 64为架构{uint64_t t;__asm__ volatile("mrs %0, cntvct_el0" : "=r"(t));return (t);}
#elsereturn (0);
#endif
}
参考:
https://www.amd.com/system/files/TechDocs/24594.pdf
https://www.intel.com/content/dam/www/public/us/en/documents/white-papers/ia-32-ia-64-benchmark-code-execution-paper.pdf
相关文章:

Java项目:星际争霸游戏(java+swing+awt界面编程+IO输入输出流+socket+udp网络通信)
源码获取:博客首页 "资源" 里下载! 功能简介: 星际争霸游戏项目,该项目实现了单人模式和多人合作模式,可记录游戏进度,新建游戏,载入历史记录等功能,多人模式下可以创建一…

GTONE清理维护建议方案
1、日志清理/home/gtone/AppGov/analyzer/log//home/gtone/AppGov/analyzer/SRC/temp//home/gtone/AppGov/WAS/logs/ 2、扩容现有磁盘空间至200GB转载于:https://www.cnblogs.com/arcer/p/4461018.html

[C#]委托和事件(讲解的非常不错)
引言 委托 和 事件在 .Net Framework中的应用非常广泛,然而,较好地理解委托和事件对很多接触C#时间不长的人来说并不容易。它们就像是一道槛儿,过了这个槛的人,觉得真是太容易了,而没有过去的人每次见到委托和事件就觉…

BZOJ1460: Pku2114 Boatherds
题目链接:点这里 题目描述:给你一棵n个点的带权有根树,有p个询问,每次询问树中是否存在一条长度为Len的路径,如果是,输出Yes否输出No. 数据范围:\(n\le1e5\,,p\le100\,,长度\le1e5\) Solution: …

centos 自定义内核模块 编译运行
简单记录一下 centos 自定义内核模块的一些编译运行记录,代码如下: 主要功能是通过rdtsc 指令直接从 CPU MSR 寄存器中获取时钟,尝试获取两次,两次之间会做一些赋值操作什么的,并记录一下时差。 #include <linux/…

os.system() 和 os.popen()
1.os.popen(command[, mode[, bufsize]]) os.system(command)2.os.popen() 功能强于os.system() , os.popen() 可以返回回显的内容,以文件描述符返回。eg:t_f os.popen ("ping 192.168.1.1")print t_f.read()或者:for line in os.popen("dir"…

Java项目:医院管理系统(java+Springboot+Maven+Mybatis+Vue+Mysql)
源码获取:博客首页 "资源" 里下载! 一、项目简述本系统功能包括:医院挂号,退号,缴费,退费,检查申请单开立,科室管理,医生开单,挂号级别,…

任意阶幻方..
1 /*coder Gxjun*/2 #include<stdio.h>3 #include<string.h>4 #include<stdlib.h>5 #define maxn 1006 int map[maxn][maxn] ;7 void creat_magic(int n,int x,int y ,int sn) //奇阶幻方构造8 {9 int i,j,k;10 i0;11 jn/2;12 for(kn;k<…

UML与软件建模 第三次作业
1.单元测试的任务有哪些? 单元测试是对软件基本组成单元进行的测试,而且软件单元是与程序的其他部分相隔离的情况下进行独立的测试. 任务主要包括对单元功能、逻辑控制、数据和安全性等各方面进行必要的测试。具体地说,包括单元中所有独立执行路径、数据…

Pliops XDP(Extreme Data Processor)数据库存储设计的新型加速硬件
文章目录0 前言1 核心问题1.1 引擎的各方面性能受限于数据结构的选择1.2 压缩功能 导致的CPU瓶颈1.3 Crash-safe 崩溃异常的无奈选择1.4 当前主流 加速硬件 较难满足存储性能提升的要求2 XDP 设计原则2.1 数据结构上的优化2.2 解决 压缩引入的CPU消耗2.3 异常恢复的设计2.4 易于…

Java项目:潜艇大战项目(java+swing)
源码获取:博客首页 "资源" 里下载! 功能简介: Java swing实现的一款小游戏潜艇大战的项目源码 游戏界面: SuppressWarnings({ "unused", "serial" }) public class GameGUI extends JPanel {//卡…

可以发张图片做链接用吗
转载于:https://www.cnblogs.com/wasss/p/4466492.html

更改显示器的分辨率
1.桌面右击,如图1-1所示。2.点击屏幕分辩率,选择分辨率调大小,确定,如图1-2所示。转载于:https://blog.51cto.com/qikai/1367734

Java 处理0x00特殊字符
Java 处理0x00特殊字符 一、0x00字符 1,0x00是ascii码的0值:NUL 2,0x00在windows系统中显示: 3,0x00在Linux中显示: ctrlV ctrl可以打出此字符 二、Java解决0x00字符 str.replaceAll("\\u0000",&…

关于 并查集(union find) 算法基本原理 以及 其 在分布式图场景的应用
二月的最后一篇水文…想写一些有意思的东西。 文章目录环检测在图数据结构中的应用深度/广度优先 检测环并查集数据结构 (Union-Find)基本概念初始化合并 union查找祖先优化1: 合并过程 利用 rank 优化路径优化2: 路径压缩(Path Compression)并查集 解决图中检测环问题环检测在…

Java项目:智能制造生产管理平台(java+SSM+mysql+Maven+Easyui+JSP)
源码获取:博客首页 "资源" 里下载! 运行环境:jdk1.8、tomcat7.0/8.5、Mysql5.7/5.1、Maven3.6/3.5、 eclipse/STS 功能简介:计划进度、设备管理、工艺监控、物料监控、质量监控、人员监控等 访问注册控制层:…

JAVA-Eclipse快捷键
Ctrl1:快速修复。CtrlD:快速删除行。ShiftEnter:快速调到下一行。CtrlF11:快速运行。Alt上下方向键:快速移动。CtrlM:光标所在视图最大化。Alt/:智能补全。Ctrl/:快速注释代码。 转载于:https://www.cnblogs.com/bluewhy/p/44669…

Android RelativeLayout属性
// 相对于给定ID控件android:layout_above 将该控件的底部置于给定ID的控件之上;android:layout_below 将该控件的底部置于给定ID的控件之下;android:layout_toLeftOf 将该控件的右边缘与给定ID的控件左边缘对齐;android:layout_toRightOf 将该控件的左边缘与给定ID的控件右边缘…

详解Azure的权限控制
注意:本文档仅限于Azure国际版,国内版略有不同Azure中的角色分配相对来说是比较复杂的的,对于任何云组织来说,云的资源访问管理权限都是一项非常重要的功能,azure中的授权系统叫做基于角色的访问控制(RBAC&…

SNMP introduction
简单网络管理协议(SNMP)首先是由Internet工程任务组织(Internet Engineering Task Force)(IETF)的研究小组为了解决Internet上的路由器管理问题而提出的。许多人认为 SNMP在IP上运行的原因是Internet运行的是TCP/IP协议,然而事实并不是这样。 SNMP被设计成与协议无…

Java项目:在线考试系统(java+SSM+mysql+JSP)
源码获取:博客首页 "资源" 里下载! 运行环境:jdk1.8、Mysql5.7、Tomcat8.5、IDEA/Eclipse 功能简介:在线考试、历史回顾、个人成绩查询等。 管理员和教师功能有:学院管理、班级管理、课程管理、教师、学生…

Keil中使用宏编译来定义DEBUG输出
使用宏编译来格式化调试信息,是一个不错的方法,即可以在需要的时候打印出信息,还可以格式化我们所需要的输出。 #define DEBUG 1 #if (DEBUG 1) #define DBG(Args...) printf(##Args) #define DBGFL(s, Args...) printf("[%s:%d]&qu…

解决用户使用临时配置文件登陆WIN7的问题
用户登录Win7后,经常会遇到 “您已使用临时配置文件登陆” 的提示,忽略此提示的用户通常在桌面上保留的文件再次重启进入后发现文件丢失了,或者原有桌面上的文件不见了,这样一定程度上降低了工作的效率.这里主要说一下如何解决此问题。用户登…

chosen.jquery.js 有搜索功能、多选功能的下拉框插件
chosen.jquery.js 有搜索功能、多选功能的下拉框插件 官方源码: https://github.com/harvesthq/chosen 该源码中的样例index.html有该插件的详细使用介绍posted on 2019-05-09 14:40 三天打鱼,两天晒网 阅读(...) 评论(...) 编辑 收藏 转载于:https://w…

MIB in SNMP
管理信息库MIB指明了网络元素所维持的变量(即能够被管理进程查询和设置的信息)。MIB给出了一个网络中所有可能的被管理对象的集合的数据结构。SNMP的管理信息库采用和域名系统DNS相似的树型结构,它的根在最上面,根没有名字。图3画…

Java项目:后台管理系统脚手架项目(java+SpringBoot+FreeMarker+mysql+JSP)
源码获取:博客首页 "资源" 里下载! 项目描述: 这是一个基于SpringBoot框架开发的后台管理系统脚手架项目。之所以称为脚手架项目,是因为这个项目复用性很强,如果以后有其他新的项目要设计后台管理系统的话&…

Extjs4.0.7 MVC Architecture异常
uncaught exception: Ext.Loader is not enabled, so dependencies cannot be resolved dynamically. Missing required class: AM.controller.User 解决方法: 在app.js最上面加上:Ext.Loader.setConfig({ enabled: true }); Ext.Loader.setConfig({ …

Mybatis常见面试题(三)
Mybatis 映射文件中,如果 A 标签通过 include 引用了 B 标签的内容,请问, B 标签能否定义在 A 标签的后面,还是说必须定义在 A 标签的前面? :虽然 Mybatis 解析 Xml 映射文件是按照顺序解析的,但是&#x…

SMI in SNMP
SNMP中,数据类型并不多。这里我们就讨论这些数据类型,而不关心这些数据类型在实际中是如何编码的。INTEGER一个变量虽然定义为整型,但也有多种形式。有些整型变量没有范围限制,有些整型变量定义为特定的数值(例如&am…

Java项目:在线拍卖竞价系统(java+SpringBoot+FreeMarker+Mysql+redis)
源码获取:博客首页 "资源" 里下载! 超级管理员:系统管理、用户管理(冻结等)、审批竞拍标的物管理、竞标类型管理、审批机构、个人提现管理(审核)、企业提现管理(审批&…