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

Linux 内核likely与unlikey

内核源码的时候经常可以看到likely()unlikely()函数,这两个函数的作用是什么?-- 先得学一学GCC提供的内建函数!!

likely和unlikely内核中的定义

# define likely(x)	__builtin_expect(!!(x), 1)
# define unlikely(x)	__builtin_expect(!!(x), 0)
# define likely_notrace(x)	likely(x)
# define unlikely_notrace(x)	unlikely(x)

内建函数
GUN C语言提供了一系列内建函数以进行优化,这些内建函数以“_builtin”(build in function)作为前缀。

  • __builtin_constant_p(x)
    判断x是否在编译时就可以被确定为常量,如果x为常量,那么返回1,否则返回0。
#define udelay(n)							\(__builtin_constant_p(n) ?					\((n) > (MAX_UDELAY_MS * 1000) ? __bad_udelay() :		\__const_udelay((n) * UDELAY_MULT)) :		\__udelay(n))
  • __builtin_expect(exp, c)
    __builtin_expect的函数原型为long __builtin_expect (long exp, long c), __builtin_expect (lexp, c)的返回值仍是exp值本身,并不会改变exp的值。

    这里的意思是exp==c的概率很大,用来引导GCC用来条件分支预测,开发人员最清楚最可能执行哪个分支,并将最有可能执行的分支告诉编译器,让编译器优化指令序列排序,使指令尽可能的顺序执行,从而提高CPU预取指令的正确性,提升CPU执行性能。

# define likely(x)	__builtin_expect(!!(x), 1)	//x为真的可能性较大
# define unlikely(x)	__builtin_expect(!!(x), 0)	//x为假的可能性较大

为什么要使用!!符号呢?
  计算机中bool逻辑只有0和1,非0即是1,当likely(x)中参数不是逻辑值时,就可以使用!!符号转化为逻辑值1或0 。比如:!!(3)=!(!(3))=!0=1,这样就把参数3转化为逻辑1了。

  1. 在执行条件分支指令时,CPU也会预取下一条指令执行,但是如果条件分支的结果为跳转到了其他指令,那CPU预取的下一条指令就没用了,这样就降低了流水线的效率。
  2. 跳转指令相对于顺序执行的指令会多消耗CPU时间,如果可以尽可能不执行跳转,也可以提高CPU性能。

实际例子来理解下

static inline void native_set_ldt(const void *addr, unsigned int entries)
{if (likely(entries == 0))asm volatile("lldt %w0"::"q" (0));else {unsigned cpu = smp_processor_id();ldt_desc ldt;set_tssldt_descriptor(&ldt, (unsigned long)addr, DESC_LDT,entries * LDT_ENTRY_SIZE - 1);write_gdt_entry(get_cpu_gdt_rw(cpu), GDT_ENTRY_LDT,&ldt, DESC_LDT);asm volatile("lldt %w0"::"q" (GDT_ENTRY_LDT*8));}
}

likely的意思是变量entries的值为0的可能性较大,那么执行if的机会大,如果以上代码likely改为unlikely,则表示entries的值不为0的可能性大一些,执行else机会大一些,加上这种修饰,编译成二进制代码时likely使得if后面的执行语句紧跟着前面的程序,unlikely使得else后面的语句紧跟着前面的程序,这样就会被cache预读取,增加程序的执行速度。

  • __builtin_prefetch(const void *addr, int rw, int locality)
    主动进行数据预取,在使用addr的值之前就把该值读到cache中,降低读取时延,从而提高性能。
    • addr
      要预取数据的地址
    • rw
      读写属性,1表示可写,0表示只读
    • locality
      数据在缓存中的时间局部属性,0表示读取完addr的值之后不用保留在缓存中,1~3表示时间局部属性逐渐增强
// inlcude/linux/prefetch.h
#ifndef ARCH_HAS_PREFETCH
#define prefetch(x) __builtin_prefetch(x)
#endif#ifndef ARCH_HAS_PREFETCHW
#define prefetchw(x) __builtin_prefetch(x,1)
#endif#ifndef ARCH_HAS_SPINLOCK_PREFETCH
#define spin_lock_prefetch(x) prefetchw(x)
#endif

prefetch()函数进行优化的例子

void __free_pages_core(struct page *page, unsigned int order)
{unsigned int nr_pages = 1 << order;struct page *p = page;unsigned int loop;/** When initializing the memmap, __init_single_page() sets the refcount* of all pages to 1 ("allocated"/"not free"). We have to set the* refcount of all involved pages to 0.*/prefetchw(p);for (loop = 0; loop < (nr_pages - 1); loop++, p++) {prefetchw(p + 1);__ClearPageReserved(p);set_page_count(p, 0);}__ClearPageReserved(p);set_page_count(p, 0);atomic_long_add(nr_pages, &page_zone(page)->managed_pages);/** Bypass PCP and place fresh pages right to the tail, primarily* relevant for memory onlining.*/__free_pages_ok(page, order, FPI_TO_TAIL | FPI_SKIP_KASAN_POISON);
}

在处理page数据结构之前,可通过prefetchw()预取到缓存中,从而提升性能。

相关文章:

Linux 内核likely与unlikey

内核源码的时候经常可以看到likely()和unlikely()函数&#xff0c;这两个函数的作用是什么&#xff1f;-- 先得学一学GCC提供的内建函数&#xff01;&#xff01; likely和unlikely内核中的定义 # define likely(x) __builtin_expect(!!(x), 1) # define unlikely(x) __built…...

成功解决主从同步异常之Slave_IO_Running显示为No的问题

前言 MySQL主从同步在做的过程中很容易出问题, 尤其是双主配置,参数多,需要在两台服务器中反复操作,容易搞错导致失败,这里汇总的是主从同步异常之Slave_IO_Running显示为No的解决方案。 文章目录 前言一. 问题重现二. 排查过程2.1 查看UUID是否相同,并修改2.2 修改完UU…...

面试阿里测开岗失败后,被面试官在朋友圈吐槽了......

前一阵子有个徒弟向我诉苦&#xff0c;说自己在参加某大厂测试面试的时候被面试官怼得哑口无言&#xff0c;场面让他一度十分尴尬印象最深的就是下面几个问题&#xff1a;根据你以前的工作经验和学习到的测试技术&#xff0c;说说你对质量保证的理解&#xff1f;非关系型数据库…...

蓝桥杯嵌入式--字符串比较在串口通信中的应用

前言今天做了个模拟题&#xff0c;大致意思是接收上位机发的字符串&#xff0c;然后执行相应操作。思路很明确&#xff0c;就是把接收到的内容进行比较&#xff0c;但是从前我只学过比较数字的方式&#xff0c;即直接用“”进行比较&#xff0c;但是字符串不能使用这个方法&…...

考研408每周一题(2019 41)

2019年(单链表&#xff09; 41.(13分)设线性表L(a1,a2,a3,...,a(n-2),a(n-1),an)采用带头结点的单链表保存&#xff0c;链表中的结点定义如下&#xff1a; typedef struct node {int data;struct node *next; } NODE; 请设计一个空间复杂度为O(1)且时间上尽可能高效的算法&…...

Angular学习笔记(一)

以下内容基于Angular 文档中文版的学习 目录 使用Angular CLI 工具创建项目 HTML标签中{{}}插入值,[]绑定属性,()绑定事件,[(ngModel)]双向绑定 绑定属性 类和样式绑定 事件绑定 双向绑定 循环 IF 定义输入属性 定义输出事件 特殊符号 模板引用变量 页面跳转(路由…...

Linux用户和权限 —— 操作演示

Linux用户和权限——操作演示认知root用户用户、用户组管理查看权限控制修改权限控制- chmod修改权限控制- chownLinux系列&#xff1a; Linux基本命令 —— 操作演示 认知root用户 root用户(超级管理员) 无论是Windows、MacOS、Linux均采用多用户的管理模式进行权限管理。…...

【华为OD机试真题2023 JAVA】单核CPU任务调度

华为OD机试真题,2023年度机试题库全覆盖,刷题指南点这里 单核CPU任务调度 知识点队列优先级队列 时间限制:1s 空间限制:256MB 限定语言:不限 题目描述: 现在有一个CPU和一些任务需要处理,已提前获知每个任务的任务ID、优先级、所需执行时间和到达时间。 CPU同时只…...

News乐鑫科技亮相德国嵌入式展 Embedded World 2023!

3 月 14 日&#xff0c;德国纽伦堡嵌入式展 Embedded World 2023 火热启幕。本届 Embedded World 主题为 “embedded. responsible. sustainable”&#xff0c;乐鑫科技 (688018.SH) 携众多 AIoT 科技成果亮相展会&#xff0c;致力于打造更智能、更互联、更绿色的物联网未来。…...

java如何创建线程

java如何创建线程1. java如何创建线程1.1 通过继承Thread类来创建线程1.2 通过实现Runnable接口来创建线程1.3 通过匿名内部类来创建线程1.4 lambda表达式1.5 通过实现Runnable接口的方式创建线程目标类的优缺点1. java如何创建线程 一个线程在Java中使用一个Thread实例来描述…...

要是早看到这篇文章,你起码少走3年弯路,20年老程序员的忠告

文章目录前言一、程序员的薪资是怎么样的&#xff1f;二、我现在的情况适合做程序员吗&#xff1f;三、大学期间到底应该学些什么&#xff1f;四、工作还是考研&#xff1f;五、总结前言 我是龙叔&#xff0c;一名工作了20多年的退休老程序员。 如果你在工作之前看到这篇文章…...

IP地址的分类

1. 前言 最初设计互联网络时&#xff0c;为了便于寻址以及层次化构造网络&#xff0c;每个IP地址包括两个标识码&#xff08;ID&#xff09;&#xff0c;即网络ID和主机ID。 同一个物理网络上的所有主机都使用同一个网络ID&#xff0c;网络上的一个主机&#xff08;包括网络上工…...

win10下使用docker运行部署nginx,mysql

一、docker的步骤&#xff1a;1.进入docker官网下载安装包2.打开控制面板 - 程序和功能 - 启用或关闭Windows功能&#xff0c;勾选Hyper-V&#xff0c;然后点击确定即可&#xff0c;如图&#xff1a;3.重新启动电脑4.启动Docker在桌面找到Docker for Windows快捷方式&#xff0…...

sprinboot车辆充电桩

sprinboot车辆充电桩演示录像2022开发语言&#xff1a;Java 框架&#xff1a;springboot JDK版本&#xff1a;JDK1.8 服务器&#xff1a;tomcat7 数据库&#xff1a;mysql 5.7&#xff08;一定要5.7版本&#xff09; 数据库工具&#xff1a;Navicat11 开发软件&#xff1a;ecli…...

仿京东放大镜效果的实现

仿京东放大镜 &#xff08;1&#xff09; 整个案例可以分为三个功能模块 &#xff08;2&#xff09; 鼠标经过小图片盒子&#xff0c; 黄色的遮挡层 和 大图片盒子显示&#xff0c;离开隐藏2个盒子功能 &#xff08;3&#xff09;黄色的遮挡层跟随鼠标功能。 &#xff08;4&…...

ESP32设备驱动-LM35温度传感器驱动

LM35温度传感器驱动 文章目录 LM35温度传感器驱动1、LM35介绍2、硬件准备3、软件准备4、驱动实现1、LM35介绍 LM35 系列是精密集成电路温度传感器,其输出电压与摄氏(摄氏度)温度成线性比例。 因此,LM35 优于以开尔文校准的线性温度传感器,因为用户无需从其输出中减去较大…...

基于深度学习的犬种识别软件(YOLOv5清新界面版,Python代码)

摘要&#xff1a;基于深度学习的犬种识别软件用于识别常见多个犬品种&#xff0c;基于YOLOv5算法检测犬种&#xff0c;并通过界面显示记录和管理&#xff0c;智能辅助人们辨别犬种。本文详细介绍博主自主开发的犬种检测系统&#xff0c;在介绍算法原理的同时&#xff0c;给出Py…...

【IDEA插件开发】环境搭建

基础信息 GRADLE 7.5.1 IDEA IntelliJ IDEA 2020.1.1 (Ultimate Edition) Build #IU-201.7223.91, built on April 30, 2020 Licensed to https://zhile.io You have a perpetual fallback license for this version Subscription is active until July 8, 2089 Runtime ve…...

【蓝桥杯专题】 DP(C++ | 洛谷 | acwing | 蓝桥)

菜狗现在才开始备战蓝桥杯QAQ 文章目录【蓝桥杯专题】 DP&#xff08;C | 洛谷 | acwing | 蓝桥&#xff09;AcWing 1205. 买不到的数目Acwing 1216. 饮料换购【模拟】01背包271. 杨老师的照相排列最长公共上升子序列PPPPPPPP总结【蓝桥杯专题】 DP&#xff08;C | 洛谷 | acwi…...

咪咕MGV3201_ZG_GK国科6323_UWE5621DS_免拆卡刷固件包

咪咕MGV3201_ZG_GK国科6323_UWE5621DS_免拆卡刷固件包 特点&#xff1a; 1、适用于对应型号的电视盒子刷机&#xff1b; 2、开放原厂固件屏蔽的市场安装和u盘安装apk&#xff1b; 3、修改dns&#xff0c;三网通用&#xff1b; 4、大量精简内置的没用的软件&#xff0c;运行…...

STM32+rt-thread判断是否联网

一、根据NETDEV_FLAG_INTERNET_UP位判断 static bool is_conncected(void) {struct netdev *dev RT_NULL;dev netdev_get_first_by_flags(NETDEV_FLAG_INTERNET_UP);if (dev RT_NULL){printf("wait netdev internet up...");return false;}else{printf("loc…...

【网络安全产品大调研系列】2. 体验漏洞扫描

前言 2023 年漏洞扫描服务市场规模预计为 3.06&#xff08;十亿美元&#xff09;。漏洞扫描服务市场行业预计将从 2024 年的 3.48&#xff08;十亿美元&#xff09;增长到 2032 年的 9.54&#xff08;十亿美元&#xff09;。预测期内漏洞扫描服务市场 CAGR&#xff08;增长率&…...

从深圳崛起的“机器之眼”:赴港乐动机器人的万亿赛道赶考路

进入2025年以来&#xff0c;尽管围绕人形机器人、具身智能等机器人赛道的质疑声不断&#xff0c;但全球市场热度依然高涨&#xff0c;入局者持续增加。 以国内市场为例&#xff0c;天眼查专业版数据显示&#xff0c;截至5月底&#xff0c;我国现存在业、存续状态的机器人相关企…...

大语言模型如何处理长文本?常用文本分割技术详解

为什么需要文本分割? 引言:为什么需要文本分割?一、基础文本分割方法1. 按段落分割(Paragraph Splitting)2. 按句子分割(Sentence Splitting)二、高级文本分割策略3. 重叠分割(Sliding Window)4. 递归分割(Recursive Splitting)三、生产级工具推荐5. 使用LangChain的…...

Java-41 深入浅出 Spring - 声明式事务的支持 事务配置 XML模式 XML+注解模式

点一下关注吧&#xff01;&#xff01;&#xff01;非常感谢&#xff01;&#xff01;持续更新&#xff01;&#xff01;&#xff01; &#x1f680; AI篇持续更新中&#xff01;&#xff08;长期更新&#xff09; 目前2025年06月05日更新到&#xff1a; AI炼丹日志-28 - Aud…...

【服务器压力测试】本地PC电脑作为服务器运行时出现卡顿和资源紧张(Windows/Linux)

要让本地PC电脑作为服务器运行时出现卡顿和资源紧张的情况&#xff0c;可以通过以下几种方式模拟或触发&#xff1a; 1. 增加CPU负载 运行大量计算密集型任务&#xff0c;例如&#xff1a; 使用多线程循环执行复杂计算&#xff08;如数学运算、加密解密等&#xff09;。运行图…...

全志A40i android7.1 调试信息打印串口由uart0改为uart3

一&#xff0c;概述 1. 目的 将调试信息打印串口由uart0改为uart3。 2. 版本信息 Uboot版本&#xff1a;2014.07&#xff1b; Kernel版本&#xff1a;Linux-3.10&#xff1b; 二&#xff0c;Uboot 1. sys_config.fex改动 使能uart3(TX:PH00 RX:PH01)&#xff0c;并让boo…...

技术栈RabbitMq的介绍和使用

目录 1. 什么是消息队列&#xff1f;2. 消息队列的优点3. RabbitMQ 消息队列概述4. RabbitMQ 安装5. Exchange 四种类型5.1 direct 精准匹配5.2 fanout 广播5.3 topic 正则匹配 6. RabbitMQ 队列模式6.1 简单队列模式6.2 工作队列模式6.3 发布/订阅模式6.4 路由模式6.5 主题模式…...

LLMs 系列实操科普(1)

写在前面&#xff1a; 本期内容我们继续 Andrej Karpathy 的《How I use LLMs》讲座内容&#xff0c;原视频时长 ~130 分钟&#xff0c;以实操演示主流的一些 LLMs 的使用&#xff0c;由于涉及到实操&#xff0c;实际上并不适合以文字整理&#xff0c;但还是决定尽量整理一份笔…...

elementUI点击浏览table所选行数据查看文档

项目场景&#xff1a; table按照要求特定的数据变成按钮可以点击 解决方案&#xff1a; <el-table-columnprop"mlname"label"名称"align"center"width"180"><template slot-scope"scope"><el-buttonv-if&qu…...