likely(x)與unlikely(x)函數,即__builtin_expect的使用

轉載自:http://velep.com/archives/795.html

?

本文講的likely()和unlikely()兩個宏,在linux內核代碼和一些應用中可常見到它們的身影。實質上,這兩個宏是關于GCC編譯器內置宏__builtin_expect的使用。

顧名思義,likely()指“很有可能”之意,而unlikely()指“不太可能”之意。那么,在實際應用中,它們代表什么?又是怎么使用的呢?下面是一篇外文翻譯(加上了本人的一些理解),給出了詳細答案。

likely()和unlikely()

對于linux內核代碼,在條件判斷語句中經常看到likely()和unlikely()的調用,如下代碼所示:

bvl = bvec_alloc(gfp_mask, nr_iovecs, &idx);
if (unlikely(!bvl)) {mempool_free(bio, bio_pool);bio = NULL;goto out;
}


在這里,調用likely()或unlikely()告訴編譯器這個條件很有可能或者不太有可能發生,好讓編譯器對這個條件判斷進行正確地優化。這兩個宏在include/linux/compiler.h文件中可以找到:

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


在GCC文檔中可找到上述代碼中__builtin_expect的說明,摘錄如下:

    -- Built-in Function: long __builtin_expect (long EXP, long C)You may use `__builtin_expect' to provide the compiler with branch
        prediction information.  In general, you should prefer to useactual profile feedback for this (`-fprofile-arcs'), as
        programmers are notoriously bad at predicting how their programsactually perform.  However, there are applications in which thisdata is hard to collect.The return value is the value of EXP, which should be an integralexpression.  The value of C must be a compile-time constant.  Thesemantics of the built-in are that it is expected that EXP == C.For example:if (__builtin_expect (x, 0))foo ();would indicate that we do not expect to call `foo', since weexpect `x' to be zero.  Since you are limited to integralexpressions for EXP, you should use constructions such asif (__builtin_expect (ptr != NULL, 1))error ();when testing pointer or floating-point values.


__builtin_expect說明中給出了兩示例:

if (__builtin_expect (x, 0)) foo (); 表示期望x == 0,也就是不期望不執行foo()函數;同理,if (__builtin_expect (ptr != NULL, 1)) error (); 表示期望指針prt非空,也就是不期望看到error()函數的執行。

編譯器做的優化工作

從GCC的說明中可知,__builtin_expect的主要作用就是:幫助編譯器判斷條件跳轉的預期值,避免因執行jmp跳轉指令造成時間浪費。那么它是怎么幫助編譯器進行優化的呢?

編譯器優化時,根據條件跳轉的預期值,按正確地順序生成匯編代碼,把“很有可能發生”的條件分支放在順序執行指令段,而不是jmp指令段(jmp指令會打亂CPU的指令執行順序,大大影響CPU指令執行效率)。

下面舉例說明。下面這個簡單的C程序使用gcc -O2進行編譯。

#define likely(x)    __builtin_expect(!!(x), 1)
#define unlikely(x)  __builtin_expect(!!(x), 0)int main(char *argv[], int argc)
{int a;/* 獲取輸入參數值(編譯器不能進行優化) */a = atoi (argv[1]);if (unlikely (a == 2))a++;elsea--;printf ("%d\n", a);return 0;
}


使用objdump -S反匯編,查看它的匯編代碼。

80483b0 <main>:
//             開頭
80483b0:       55                      push   %ebp
80483b1:       89 e5                   mov    %esp,%ebp
80483b3:       50                      push   %eax
80483b4:       50                      push   %eax
80483b5:       83 e4 f0                and    $0xfffffff0,%esp
//             調用atoi()
80483b8:       8b 45 08                mov    0x8(%ebp),%eax
80483bb:       83 ec 1c                sub    $0x1c,%esp
80483be:       8b 48 04                mov    0x4(%eax),%ecx
80483c1:       51                      push   %ecx
80483c2:       e8 1d ff ff ff          call   80482e4 <atoi@plt>
80483c7:       83 c4 10                add    $0x10,%esp
//             把輸入值與2進行比較,即執行:“a == 2”
80483ca:       83 f8 02                cmp    $0x2,%eax
//             --------------------------------------------------------
//             如果'a' 等于 2 (程序里面認為不太可能), 則跳轉,
//             否則繼續執行, 從而不破壞CPU的指令執行順序.
//             --------------------------------------------------------
80483cd:       74 12                   je     80483e1 <main+0x31>
80483cf:       48                      dec    %eax
//             調用printf
80483d0:       52                      push   %edx
80483d1:       52                      push   %edx
80483d2:       50                      push   %eax
80483d3:       68 c8 84 04 08          push   $0x80484c8
80483d8:       e8 f7 fe ff ff          call   80482d4 <printf@plt>
//             返回0并退出.
80483dd:       31 c0                   xor    %eax,%eax
80483df:       c9                      leave
80483e0:       c3                      ret


在上面程序中,用likely()代替其中的unlikely(),重新編譯,再來看它的匯編代碼:

80483b0 <main>:
//             開頭
80483b0:       55                      push   %ebp
80483b1:       89 e5                   mov    %esp,%ebp
80483b3:       50                      push   %eax
80483b4:       50                      push   %eax
80483b5:       83 e4 f0                and    $0xfffffff0,%esp
//             調用atoi()
80483b8:       8b 45 08                mov    0x8(%ebp),%eax
80483bb:       83 ec 1c                sub    $0x1c,%esp
80483be:       8b 48 04                mov    0x4(%eax),%ecx
80483c1:       51                      push   %ecx
80483c2:       e8 1d ff ff ff          call   80482e4 <atoi@plt>
80483c7:       83 c4 10                add    $0x10,%esp
//             --------------------------------------------------
//             如果'a' 等于 2 (程序認為很有可能), 則不跳轉,繼續執行,
//             這樣就不破壞CPU的指令執行順序.
//             只有當 a != 2 時才會發生跳轉, 而這種情況,程序認為是不太可能的.
//             ---------------------------------------------------
80483ca:       83 f8 02                cmp    $0x2,%eax
80483cd:       75 13                   jne    80483e2 <main+0x32>
//             a++ 指令的優化
80483cf:       b0 03                   mov    $0x3,%al
//             調用printf()
80483d1:       52                      push   %edx
80483d2:       52                      push   %edx
80483d3:       50                      push   %eax
80483d4:       68 c8 84 04 08          push   $0x80484c8
80483d9:       e8 f6 fe ff ff          call   80482d4 <printf@plt>
//             返回0并退出.
80483de:       31 c0                   xor    %eax,%eax
80483e0:       c9                      leave
80483e1:       c3                      ret


如何使用?

在一個條件判斷語句中,當這個條件被認為是非常非常有可能滿足時,則使用likely()宏,否則,條件非常非常不可能或很難滿足時,則使用unlikely()宏。

參考資料

本文英文原文:http://kernelnewbies.org/FAQ/LikelyUnlikely

更多GCC內置宏或函數,詳見:http://gcc.gnu.org/onlinedocs/gcc/Other-Builtins.html

轉載于:https://www.cnblogs.com/pengdonglin137/articles/3808631.html

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/260312.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/260312.shtml
英文地址,請注明出處:http://en.pswp.cn/news/260312.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

java mvc引擎_SpringMvc+JavaConfig+Idea 搭建項目

1.介紹之前搭建SpringMvc項目要配置一系列的配置文件&#xff0c;比如web.xml,applicationContext.xml,dispatcher.xml。Spring 3.X之后推出了基于JavaConfig方式以及注解的形式的配置。在一定程度上簡化了Spring項目的配置。近幾年特別火的SpringBoot&#xff0c;大大的簡化了…

window.parent和window.opener區別

下面一段代碼是關于window.parent和window.opener區別 來講的&#xff0c;我們如果要用到iframe的值傳到另一框架就要用到window.opener.document.getElementById(name).value uvalue;這種形式哦。 window.parent能獲取一個框架的父窗口或父框架。頂層窗口的parent引用的是它本…

極域電子書包課堂管理系統_【君蓮微訊】君蓮學校(小學部)開展電子書包第13共同體數學研討活動...

借 助 媒 體 技 術豐 富 圖 形 認 識君蓮學校(小學部)開展電子書包共同體 數學研討活動 2020年12月2日下午&#xff0c;君蓮學校(小學部)開展了以“借助媒體技術 豐富圖形認識”為主題的閔行區電子書包第13共同體的數學研討活動。共同體學校教師代表、學校電子書包項目組主管朱…

python批量改動指定文件夾文件名稱

這小樣例僅僅要是說明用python怎么批量改動指定文件夾的文件名稱&#xff1a; 記得要把腳本跟改動的文件放在同一個文件夾下 #encoding:utf-8 import os import sys files os.listdir(D:\\1) #路徑能夠自己for name in files:a os.path.splitext(name)if a[1] .txt: #txt能夠…

Linux vmstat命令實戰詳解

vmstat命令是最常見的Linux/Unix監控工具&#xff0c;可以展現給定時間間隔的服務器的狀態值,包括服務器的CPU使用率&#xff0c;內存使用&#xff0c;虛擬內存交換情況,IO讀寫情況。這個命令是我查看Linux/Unix最喜愛的命令&#xff0c;一個是Linux/Unix都支持&#xff0c;二是…

python的基礎網絡編程是下列_Python入門基礎之網絡編程、socket編程、TCP、UDP編程...

忙了兩天&#xff0c;繼續更文&#xff01;希望多多支持。套接字套接字是一種具有之前所說的"通訊端點"概念的計算機網絡數據結構。網絡化的應用程序在開始任何通訊之前都必需要創建套接字。套接字有三種&#xff1a;1、 AF_UNIX(在 POSIX1.g 標準中也叫 AF_LOCAL)&a…

java 入門 博客園_javaweb入門

復習&#xff1a;css的常用樣式&#xff1a;borderbackgroundpaddingmarginfloatposition 定位top left確定div在頁面中的位置&#xff0c;這兩個值可以為負數。cssdiv 布局方式cssdivtable 先由div劃分大塊兒&#xff0c;再由table進行整齊布局。下拉列表&#xff1a;層疊的布…

以ThreadStart方式實現多線程

3.1 使用ThreadStart委托 這里先以一個例子體現一下多線程帶來的好處&#xff0c;首先在Message類中建立一個方法ShowMessage()&#xff0c;里面顯示了當前運行線程的Id&#xff0c;并使用Thread.Sleep&#xff08;int ) 方法模擬部分工作。在main()中通過ThreadStart委托綁定M…

管理思考

管理基礎 分活 分錢 分責任 分權 安人(安排 配置) 流程 標準 考核 治人(協調 指揮 控制) 社會越來越復雜 分工越來越復雜 合作越來越重要 目標一定要一致共同的意愿共識 需要大家參與管理 業務劃分 責任劃分 流程梳理 如何合作做好安全工作 安全服務因為不承擔責任 責任主體是管…

我的atom插件

atom插件實在是太多了&#xff0c;下面就說說我的插件 1.minimap 右邊的小地圖&#xff0c;和sublime里面的差不多&#xff1b; 2.open-in-browser 右擊默認瀏覽器打開&#xff1b; 3.emmet 這個不用多說吧&#xff0c;html快速編譯 4.git-plus 直接在atom提交代碼&#xff0…

python統計英文句子每個單詞字數_Python小書3-文本英文單詞統計

之前寫Python Web小書第三小節本來用的垃圾郵件的案例三郎&#xff1a;Python貝葉斯推理垃圾郵件分類?zhuanlan.zhihu.com后來發現里面的東西&#xff0c;涉及到概率&#xff0c;程序太復雜了。。。哈哈哈所以就想著&#xff0c;哪天重寫一下&#xff0c;選來選去&#xff0c;…

java9特性_96.java基礎10(java9/10/11新特性)

126.java 9 新特性1(模塊化功能):1.java模塊化2.java 交互式環境jshell3.泛型package com.atguigu.java;import org.junit.Test;import java.io.IOException;import java.io.InputStreamReader;import java.net.MalformedURLException;import java.net.URL;import java.util.Ar…

MonoRail - 簡介 [基礎知識篇]

MonoRail - 簡介 起源 MonoRail是一個.NET的MVC web開發框架, 原名Castle On Rails, 是CastleProject的一個子項目. 作者hammett在使用過Ruby On Rails后, 覺得非常棒, 他希望在享受ror的開發模式的同時能使用大量現有的資源, 于是就用.NET寫出了一個Castle On Rails. 后來ror那…

結對編程(黃金點游戲)

我扮演的角色是駕駛員 一、結對伙伴 領航員&#xff1a;趙峻 作業地址見我的博客。 二、代碼地址 https://coding.net/u/k2048/p/huangjindian/git/blob/master/main.c 三、總結 1、個人總結 本次作業我扮演駕駛員&#xff0c;趙峻扮演領航員&#xff0c;我負責算法實現以及代碼…

qtgl 鼠標平移 c++_羅技真愛粉的MX Master 3無線鼠標體驗

?這是一篇關于羅技MX Master3的曬單&#xff0c;順帶也翻出我的庫存清潔整理一下吧。在決定購買一款新鼠標的時候&#xff0c;我的第一目標其實是MX Vertical垂直鼠標&#xff0c;不過MX Vertical目前優勢只在外形上&#xff0c;在MX系列中明顯屬于低配&#xff0c;自由滾輪、…

java實驗指導書(實驗四)答案_java程序設計實驗指導書答案

? 狗生活在陸地上(是一種陸生動物)&#xff0c;既是哺乳類的也是肉食性的。狗通常的時候和人打招呼會通過“搖搖尾巴”&#xff0c;在被撫摸感到舒服的時候&#xff0c;會“旺旺叫”&#xff0c;而在受到驚嚇情緒煩躁時&#xff0c;會發出“嗚嗚”聲&#xff1b;? 貓也生活在…

php代碼規范說明文檔

命名規則&#xff1a;采用駝峰標識&#xff0c;盡量做到見名知義 PHP編碼規范與原則&#xff1a; //命名&#xff1a;類&#xff0c;方法&#xff0c;函數&#xff0c;變量&#xff0c; 注釋&#xff1a;開發中難免留下一些臨時代碼和調試代碼&#xff0c;此類代碼必須添加注釋…

下載網頁中的圖片到本地

簡單的一個下載如下 &#xff1a; string url "http://avatar.csdn.net/A/2/6/2_yefengzhixia.jpg";string filepath "D:\\pic.jpg";WebClient mywebclient new WebClient();mywebclient.DownloadFile(url, filepath);MessageBox.Show("OK");…

nacos linux啟動_微服務系列之Nacos配置中心之一:Nacos介紹與安裝

一、Nacos 介紹Nacos 是 Alibaba 公司推出的開源工具&#xff0c;用于實現分布式系統的服務發現與配置管理。英文全稱 Dynamic Naming and Configuration Service&#xff0c;Na 為 Naming/NameServer 即注冊中心&#xff0c;co 為 Configuration 即配置中心&#xff0c;Servic…

演練:在組件設計器中創建 Windows 服務應用程序

http://msdn.microsoft.com/zh-cn/library/zt39148a(vvs.80).aspx 演練&#xff1a;在組件設計器中創建 Windows 服務應用程序 .NET Framework 2.0其他版本5&#xff08;共 5&#xff09;對本文的評價是有幫助 - 評價此主題注意 Visual Studio 標準版中不提供“Windows 服務”模…