当前位置: 首页 > 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;运行…...

【入坑系列】TiDB 强制索引在不同库下不生效问题

文章目录 背景SQL 优化情况线上SQL运行情况分析怀疑1:执行计划绑定问题?尝试:SHOW WARNINGS 查看警告探索 TiDB 的 USE_INDEX 写法Hint 不生效问题排查解决参考背景 项目中使用 TiDB 数据库,并对 SQL 进行优化了,添加了强制索引。 UAT 环境已经生效,但 PROD 环境强制索…...

蓝牙 BLE 扫描面试题大全(2):进阶面试题与实战演练

前文覆盖了 BLE 扫描的基础概念与经典问题蓝牙 BLE 扫描面试题大全(1)&#xff1a;从基础到实战的深度解析-CSDN博客&#xff0c;但实际面试中&#xff0c;企业更关注候选人对复杂场景的应对能力&#xff08;如多设备并发扫描、低功耗与高发现率的平衡&#xff09;和前沿技术的…...

【算法训练营Day07】字符串part1

文章目录 反转字符串反转字符串II替换数字 反转字符串 题目链接&#xff1a;344. 反转字符串 双指针法&#xff0c;两个指针的元素直接调转即可 class Solution {public void reverseString(char[] s) {int head 0;int end s.length - 1;while(head < end) {char temp …...

css的定位(position)详解:相对定位 绝对定位 固定定位

在 CSS 中&#xff0c;元素的定位通过 position 属性控制&#xff0c;共有 5 种定位模式&#xff1a;static&#xff08;静态定位&#xff09;、relative&#xff08;相对定位&#xff09;、absolute&#xff08;绝对定位&#xff09;、fixed&#xff08;固定定位&#xff09;和…...

AI编程--插件对比分析:CodeRider、GitHub Copilot及其他

AI编程插件对比分析&#xff1a;CodeRider、GitHub Copilot及其他 随着人工智能技术的快速发展&#xff0c;AI编程插件已成为提升开发者生产力的重要工具。CodeRider和GitHub Copilot作为市场上的领先者&#xff0c;分别以其独特的特性和生态系统吸引了大量开发者。本文将从功…...

【HTTP三个基础问题】

面试官您好&#xff01;HTTP是超文本传输协议&#xff0c;是互联网上客户端和服务器之间传输超文本数据&#xff08;比如文字、图片、音频、视频等&#xff09;的核心协议&#xff0c;当前互联网应用最广泛的版本是HTTP1.1&#xff0c;它基于经典的C/S模型&#xff0c;也就是客…...

2025季度云服务器排行榜

在全球云服务器市场&#xff0c;各厂商的排名和地位并非一成不变&#xff0c;而是由其独特的优势、战略布局和市场适应性共同决定的。以下是根据2025年市场趋势&#xff0c;对主要云服务器厂商在排行榜中占据重要位置的原因和优势进行深度分析&#xff1a; 一、全球“三巨头”…...

短视频矩阵系统文案创作功能开发实践,定制化开发

在短视频行业迅猛发展的当下&#xff0c;企业和个人创作者为了扩大影响力、提升传播效果&#xff0c;纷纷采用短视频矩阵运营策略&#xff0c;同时管理多个平台、多个账号的内容发布。然而&#xff0c;频繁的文案创作需求让运营者疲于应对&#xff0c;如何高效产出高质量文案成…...

VM虚拟机网络配置(ubuntu24桥接模式):配置静态IP

编辑-虚拟网络编辑器-更改设置 选择桥接模式&#xff0c;然后找到相应的网卡&#xff08;可以查看自己本机的网络连接&#xff09; windows连接的网络点击查看属性 编辑虚拟机设置更改网络配置&#xff0c;选择刚才配置的桥接模式 静态ip设置&#xff1a; 我用的ubuntu24桌…...

处理vxe-table 表尾数据是单独一个接口,表格tableData数据更新后,需要点击两下,表尾才是正确的

修改bug思路&#xff1a; 分别把 tabledata 和 表尾相关数据 console.log() 发现 更新数据先后顺序不对 settimeout延迟查询表格接口 ——测试可行 升级↑&#xff1a;async await 等接口返回后再开始下一个接口查询 ________________________________________________________…...