国产亚洲精品福利在线无卡一,国产精久久一区二区三区,亚洲精品无码国模,精品久久久久久无码专区不卡

當(dāng)前位置: 首頁(yè) > news >正文

個(gè)門戶網(wǎng)站站長(zhǎng)之家ip查詢工具

個(gè)門戶網(wǎng)站,站長(zhǎng)之家ip查詢工具,無錫網(wǎng)站建設(shè) 君通科技,開網(wǎng)站做賭博賺錢嗎文章目錄 背景1. static-key的使用方法1.1. static-key定義1.2 初始化1.3 條件判斷1.4 修改判斷條件 2、示例代碼參考鏈接 背景 內(nèi)核中有很多判斷條件在正常情況下的結(jié)果都是固定的,除非極其罕見的場(chǎng)景才會(huì)改變,通常單個(gè)的這種判斷的代價(jià)很低可以忽略&a…

文章目錄

  • 背景
  • 1. static-key的使用方法
    • 1.1. static-key定義
    • 1.2 初始化
    • 1.3 條件判斷
    • 1.4 修改判斷條件
  • 2、示例代碼
    • 參考鏈接

背景

內(nèi)核中有很多判斷條件在正常情況下的結(jié)果都是固定的,除非極其罕見的場(chǎng)景才會(huì)改變,通常單個(gè)的這種判斷的代價(jià)很低可以忽略,但是如果這種判斷數(shù)量巨大且被頻繁執(zhí)行,那就會(huì)帶來性能損失了。內(nèi)核的static-key機(jī)制就是為了優(yōu)化這種場(chǎng)景,其優(yōu)化的結(jié)果是:對(duì)于大多數(shù)情況,對(duì)應(yīng)的判斷被優(yōu)化為一個(gè)NOP指令,在非常有場(chǎng)景的時(shí)候就變成jump XXX一類的指令,使得對(duì)應(yīng)的代碼段得到執(zhí)行。
在這里插入圖片描述

1. static-key的使用方法

1.1. static-key定義

static_key 結(jié)構(gòu)體的定義如下:

#ifdef CONFIG_JUMP_LABELstruct static_key {atomic_t enabled;
/** Note:*   To make anonymous unions work with old compilers, the static*   initialization of them requires brackets. This creates a dependency*   on the order of the struct with the initializers. If any fields*   are added, STATIC_KEY_INIT_TRUE and STATIC_KEY_INIT_FALSE may need*   to be modified.** bit 0 => 1 if key is initially true*	    0 if initially false* bit 1 => 1 if points to struct static_key_mod*	    0 if points to struct jump_entry*/union {unsigned long type;struct jump_entry *entries;struct static_key_mod *next;};
};#else
struct static_key {atomic_t enabled;
};
#endif	/* CONFIG_JUMP_LABEL */

如果沒有定義CONFIG_JUMP_LABEL,則static_key 退化成atomic變量。

1.2 初始化

#define DEFINE_STATIC_KEY_TRUE(name)	\struct static_key_true name = STATIC_KEY_TRUE_INIT
#define DEFINE_STATIC_KEY_FALSE(name)	\struct static_key_false name = STATIC_KEY_FALSE_INIT
#define STATIC_KEY_TRUE_INIT  (struct static_key_true) { .key = STATIC_KEY_INIT_TRUE,  }
#define STATIC_KEY_FALSE_INIT (struct static_key_false){ .key = STATIC_KEY_INIT_FALSE, }#define STATIC_KEY_INIT_TRUE                    \{ .enabled = { 1 },                    \.entries = (void *)JUMP_TYPE_TRUE }
#define STATIC_KEY_INIT_FALSE                    \{ .enabled = { 0 },                    \.entries = (void *)JUMP_TYPE_FALSE }

false和true的主要區(qū)別就是enabled 是否為1.

1.3 條件判斷

#ifdef CONFIG_JUMP_LABEL/** Combine the right initial value (type) with the right branch order* to generate the desired result.*** type\branch|	likely (1)	      |	unlikely (0)* -----------+-----------------------+------------------*            |                       |*  true (1)  |	   ...		      |	   ...*            |    NOP		      |	   JMP L*            |    <br-stmts>	      |	1: ...*            |	L: ...		      |*            |			      |*            |			      |	L: <br-stmts>*            |			      |	   jmp 1b*            |                       |* -----------+-----------------------+------------------*            |                       |*  false (0) |	   ...		      |	   ...*            |    JMP L	      |	   NOP*            |    <br-stmts>	      |	1: ...*            |	L: ...		      |*            |			      |*            |			      |	L: <br-stmts>*            |			      |	   jmp 1b*            |                       |* -----------+-----------------------+------------------** The initial value is encoded in the LSB of static_key::entries,* type: 0 = false, 1 = true.** The branch type is encoded in the LSB of jump_entry::key,* branch: 0 = unlikely, 1 = likely.** This gives the following logic table:**	enabled	type	branch	  instuction* -----------------------------+-----------*	0	0	0	| NOP*	0	0	1	| JMP*	0	1	0	| NOP*	0	1	1	| JMP**	1	0	0	| JMP*	1	0	1	| NOP*	1	1	0	| JMP*	1	1	1	| NOP** Which gives the following functions:**   dynamic: instruction = enabled ^ branch*   static:  instruction = type ^ branch** See jump_label_type() / jump_label_init_type().*/#define static_branch_likely(x)							\
({										\bool branch;								\if (__builtin_types_compatible_p(typeof(*x), struct static_key_true))	\branch = !arch_static_branch(&(x)->key, true);			\else if (__builtin_types_compatible_p(typeof(*x), struct static_key_false)) \branch = !arch_static_branch_jump(&(x)->key, true);		\else									\branch = ____wrong_branch_error();				\likely(branch);								\
})#define static_branch_unlikely(x)						\
({										\bool branch;								\if (__builtin_types_compatible_p(typeof(*x), struct static_key_true))	\branch = arch_static_branch_jump(&(x)->key, false);		\else if (__builtin_types_compatible_p(typeof(*x), struct static_key_false)) \branch = arch_static_branch(&(x)->key, false);			\else									\branch = ____wrong_branch_error();				\unlikely(branch);							\
})#else /* !CONFIG_JUMP_LABEL */#define static_branch_likely(x)		likely(static_key_enabled(&(x)->key))
#define static_branch_unlikely(x)	unlikely(static_key_enabled(&(x)->key))#endif /* CONFIG_JUMP_LABEL */

可見同樣依賴HAVE_JUMP_LABEL。如果沒有定義的話,直接退化成likely和unlikely
static_branch_unlikelystatic_branch_likely 只是填充指令的方式不同(可以參考上面的代碼注釋), 當(dāng)static_key為false時(shí),都會(huì)進(jìn)入else邏輯語句中。

if (static_branch_unlikely((&static_key)))do likely work;
elsedo unlikely work

1.4 修改判斷條件

使用static_branch_enablestatic_branch_disable可以改變static_key 狀態(tài)

#define static_branch_enable(x)        static_key_enable(&(x)->key)
#define static_branch_disable(x)    static_key_disable(&(x)->key)

底層是調(diào)用static_key_slow_dec, static_key_slow_dec來改變key->enabled計(jì)數(shù)。

static inline void static_key_enable(struct static_key *key)
{int count = static_key_count(key);WARN_ON_ONCE(count < 0 || count > 1);if (!count)static_key_slow_inc(key);
}
static inline void static_key_disable(struct static_key *key)
{int count = static_key_count(key);WARN_ON_ONCE(count < 0 || count > 1);if (count)static_key_slow_dec(key);
}
static inline void static_key_slow_inc(struct static_key *key)
{STATIC_KEY_CHECK_USE(key);atomic_inc(&key->enabled);
}static inline void static_key_slow_dec(struct static_key *key)
{STATIC_KEY_CHECK_USE(key);atomic_dec(&key->enabled);
}

2、示例代碼

下面我們用一段代碼來分析static-key對(duì)程序分支跳轉(zhuǎn)硬編碼的影響。

#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/static_key.h>DEFINE_STATIC_KEY_FALSE(key);void func(int a){if (static_branch_unlikely(&key)) {  printk("my_module: Feature is enabled\n");} else {printk("my_module: Feature is disabled\n");}
}static int __init my_module_init(void) {pr_info("my_module: Module loaded\n");int a = 1;func(a);static_branch_enable(&key);func(a);return 0;
}static void __exit my_module_exit(void) {pr_info("my_module: Module unloaded\n");
}module_init(my_module_init);
module_exit(my_module_exit);MODULE_LICENSE("GPL");
MODULE_AUTHOR("Your Name");
MODULE_DESCRIPTION("Sample Kernel Module with Static Key");

func匯編代碼如下:

0000000000000000 <func>:0:   a9bf7bfd        stp     x29, x30, [sp, #-16]!4:   910003fd        mov     x29, sp8:   d503201f        nopc:   90000000        adrp    x0, 0 <func>10:   91000000        add     x0, x0, #0x014:   94000000        bl      0 <printk>18:   a8c17bfd        ldp     x29, x30, [sp], #161c:   d65f03c0        ret20:   90000000        adrp    x0, 0 <func>24:   91000000        add     x0, x0, #0x028:   94000000        bl      0 <printk>2c:   17fffffb        b       18 <func+0x18>

func中不適用static-key時(shí),匯編代碼如下:

void func(int a){if (a) {  printk("my_module: Feature is enabled\n");} else {printk("my_module: Feature is disabled\n");}
}0000000000000000 <func>:0:   a9bf7bfd        stp     x29, x30, [sp, #-16]!4:   910003fd        mov     x29, sp8:   340000a0        cbz     w0, 1c <func+0x1c>c:   90000000        adrp    x0, 0 <func>10:   91000000        add     x0, x0, #0x014:   94000000        bl      0 <printk>18:   14000004        b       28 <func+0x28>1c:   90000000        adrp    x0, 0 <func>20:   91000000        add     x0, x0, #0x024:   94000000        bl      0 <printk>28:   a8c17bfd        ldp     x29, x30, [sp], #162c:   d65f03c0        ret

對(duì)比可以發(fā)現(xiàn),在0x8地址處,使用static-key編碼在編譯時(shí)將cbz指令替換為了nop指令,減少了程序運(yùn)行時(shí)對(duì)比次數(shù)。

參考鏈接

  1. Linux內(nèi)核中的static-key機(jī)制
  2. Linux內(nèi)核jump label與static key的原理與示例
  3. static-keys.html | 靜態(tài)鍵
  4. Linux Jump Label/static-key機(jī)制詳解
http://m.aloenet.com.cn/news/44585.html

相關(guān)文章:

  • 網(wǎng)站二次開發(fā)是什么意思谷歌在線瀏覽器入口
  • 天津網(wǎng)站制作費(fèi)用競(jìng)價(jià)防惡意點(diǎn)擊
  • 怎么注冊(cè)英文網(wǎng)站域名a5站長(zhǎng)網(wǎng)網(wǎng)站交易
  • 武漢網(wǎng)上商城網(wǎng)站建設(shè)南通做網(wǎng)站推廣的公司
  • 鹽城網(wǎng)站開發(fā)英文谷歌優(yōu)化
  • 鄭州做網(wǎng)站優(yōu)化電話seo基礎(chǔ)入門
  • 百度怎么開戶做網(wǎng)站百度推廣平臺(tái)首頁(yè)
  • 湖南高端網(wǎng)站建設(shè)什么是搜索引擎優(yōu)化?
  • 陜西省經(jīng)營(yíng)性網(wǎng)站備案青島網(wǎng)站推廣關(guān)鍵詞
  • 北大青鳥學(xué)費(fèi)一覽表浙江seo推廣
  • 網(wǎng)站怎么做外部?jī)?yōu)化北京網(wǎng)站營(yíng)銷與推廣
  • 自己做的網(wǎng)站有什么用軟文推廣收費(fèi)
  • 網(wǎng)站開發(fā)學(xué)習(xí)視頻seo推廣知識(shí)
  • 套別人的網(wǎng)站模板嗎百度推廣登錄入口官網(wǎng)網(wǎng)
  • 福州企業(yè)制作網(wǎng)站友點(diǎn)企業(yè)網(wǎng)站管理系統(tǒng)
  • 房地產(chǎn)型網(wǎng)站建設(shè)搜索引擎的使用方法和技巧
  • 東莞網(wǎng)站營(yíng)銷網(wǎng)絡(luò)營(yíng)銷推廣公司
  • 自己做的網(wǎng)站視頻播放不了營(yíng)銷云
  • 網(wǎng)站平臺(tái)怎么做的好天津seo網(wǎng)絡(luò)營(yíng)銷
  • app網(wǎng)站建設(shè)思路有免費(fèi)做網(wǎng)站的嗎
  • 麻將網(wǎng)站怎么做的衡水seo營(yíng)銷
  • 衡陽網(wǎng)站建設(shè)icp備seo優(yōu)化網(wǎng)站推廣全域營(yíng)銷獲客公司
  • 網(wǎng)站的空間是服務(wù)器嗎營(yíng)銷網(wǎng)站建設(shè)哪家快
  • 賣手機(jī)網(wǎng)站開發(fā)的必要性百度推廣怎么樣才有效果
  • 響應(yīng)式網(wǎng)站設(shè)計(jì)案例seo網(wǎng)絡(luò)推廣技術(shù)
  • 專門做中文音譯歌曲的網(wǎng)站新網(wǎng)域名注冊(cè)官網(wǎng)
  • 禹城做網(wǎng)站的公司世界大學(xué)排名
  • 上海達(dá)安做的無創(chuàng)dna網(wǎng)站煙臺(tái)網(wǎng)絡(luò)推廣
  • 寧波論壇建站模板seo收費(fèi)低
  • 做宣傳手冊(cè)的網(wǎng)站前端性能優(yōu)化有哪些方法