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

linux c/c++最高效的计时方法

每个cpu的core在执行指令(代码)的时候,身边有约30大悍将(寄存器)在辅做,比如最典型的EBP、ESP,当要发生运行空间切换(syscall、中断),这30个寄存器里的数据是不是都要存起来以待再切回来时恢复继续接着干;

几个问题:

什么时候存?

谁存?

存在哪?

什么时候恢复?

最主要这个过程耗时多久?本文syscal揭开耗时的面纱。

程序的大致要干的事;

对64MB 循环访问一把;

连续20次调用同一个syscall函数,并分别记录每次的耗时;

printf 20次的耗时;

循环以上三步骤;

main_syscall.c

#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <unistd.h>
#include <sys/types.h>

#include “common.h”

#define LOOPCNT 20

#define BLOCKLEN 1000000

int g_aiData[BLOCKLEN][16];

int main(int argc, char ** argv)
{
int i;
long long t1, t2;
struct timespec stTP;

long long aldiff[LOOPCNT] = { 0 };
int iTemp = 0;

while(1)
{
    for (i = 0; i < BLOCKLEN; i++) /* 64MB的内存先访问一把,把L1 L2 L3尽力刷一把 */
        g_aiData[i][0] = i;

    aldiff[0] = 0;
     
    for (i = 0; i < LOOPCNT; i++)
    {
        t1 = rte_rdtsc();  /* 直接从rdtsc寄存器取,注:这个是x86_64上的 */
        getnstime(&stTP);  /* 这个函数会走syscall进内核 */
        t2 = rte_rdtsc();
        aldiff[i] = t2 - t1;
    }
     
    printf("----------------------------\n");
    for (i = 0; i < LOOPCNT; i++)
    {
        printf("%d:%lld, ", i, aldiff[i]);
    }
    printf("\n");
}
 
return 0;

}

common.c

#include <sys/time.h>
#include <time.h>
#include <stdlib.h>
#include <stdio.h>
#include “common.h”

//typedef unsigned long long uint64_t;

long long getustime(void)
{
struct timeval tv;
long long ust;

gettimeofday(&tv, NULL);
ust = ((long)tv.tv_sec)*1000000;
ust += tv.tv_usec;
return ust;

}

void getnstime(struct timespec pstTP)
{
clock_gettime(CLOCK_MONOTONIC_RAW, pstTP); /
这里带RAW的是会syscall进内核的 */
return;
}

long diff_nstime(struct timespec *pstTP1, struct timespec *pstTP2)
{
return (pstTP2->tv_sec - pstTP1->tv_sec)*1000000000 + pstTP2->tv_nsec - pstTP1->tv_nsec;
}

inline long long rte_rdtsc(void)
{
union {
long long tsc_64;
struct {
unsigned int lo_32;
unsigned int hi_32;
};
} tsc;

asm volatile("rdtsc" :
         "=a" (tsc.lo_32),
         "=d" (tsc.hi_32));
return tsc.tsc_64;

}
common.h

#ifndef COMMON_H_
#define COMMON_H_

#define ERROR_SUCCESS 0
#define ERROR_FAIL 1
#define IN
#define OUT
#define INOUT

#define CACHE_LINE 64

//#define HASHSIZE 1*1024

typedef unsigned long ulong_t;
long long getustime(void);
void getnstime(struct timespec *pstTP);
long diff_nstime(struct timespec *pstTP1, struct timespec *pstTP2);
inline long long rte_rdtsc(void);
#endif

可以看出,每轮都是第1次耗时最长,约3000(计时单位是时钟周期)这个量级,后面接着的都是300,相差了近10倍;

为什么会是这样?

我们平常调的系统调用都是每轮第1次这个样子么?


http://www.kler.cn/a/393739.html

相关文章:

  • C++单例模式与多例模式
  • Python提取PDF和DOCX中的文本、图片和表格
  • 免费,WPS Office教育考试专用版
  • Pycharm PyQt5 环境搭建创建第一个Hello程序
  • 移动端【01】面试系统的MVVM重构实践
  • 猿创征文|Inscode桌面IDE:打造高效开发新体验
  • Oracle 19c PDB克隆后出现Warning: PDB altered with errors受限模式处理
  • 花了36元给我的个人博客上了一道防御
  • 单元测试、集成测试、系统测试、验收测试、压力测试、性能测试、安全性测试、兼容性测试、回归测试(超详细的分类介绍及教学)
  • 【操作系统】守护进程
  • 多模态大模型(2)--BLIP
  • 基于springboot的物品回收系统
  • 动手学深度学习69 BERT预训练
  • vue3入门知识(二)
  • Linux 网络编程
  • 开源模型应用落地-qwen模型小试-Qwen2.5-7B-Instruct-tool usage入门-集成心知天气(二)
  • Linux源码阅读笔记-V4L2框架基础介绍
  • 基于微信小程序的计算机实验室排课与查询系统
  • ubuntu22.04与ubuntu24.10使用Remmina远程桌面共享
  • android开发
  • 主动测量View的宽高
  • 隧道技术-tcp封装icmp出网
  • 【前端】技术演进发展简史
  • 统计HBase表记录条数的方法
  • shellLoad
  • 机器学习(1)线性回归