偷偷摘套内射激情视频,久久精品99国产国产精,中文字幕无线乱码人妻,中文在线中文a,性爽19p

性能優(yōu)化,我們應(yīng)該知道的更多一點(diǎn)

運(yùn)維 系統(tǒng)運(yùn)維
當(dāng)我們談到性能優(yōu)化,更多的同學(xué)可能想到的是系統(tǒng)層面的性能優(yōu)化,而對(duì)于程序代碼本身的優(yōu)化卻比較少。實(shí)際上,除了系統(tǒng)層面的性能優(yōu)化外,在程序代碼層面的性能優(yōu)化效果也是非常好的。

當(dāng)我們談到性能優(yōu)化,更多的同學(xué)可能想到的是系統(tǒng)層面的性能優(yōu)化。比如在一個(gè)Web服務(wù)程序中,通過(guò)Redis或者其它緩存來(lái)提升網(wǎng)站訪問(wèn)的速度等。對(duì)于程序代碼本身的優(yōu)化卻比較少。這一方面是編譯器為我們做了很多優(yōu)化工作,另外一方面是覺(jué)得系統(tǒng)層面的優(yōu)化效果更明顯,也更高大上。實(shí)際上,除了系統(tǒng)層面的性能優(yōu)化外,在程序代碼層面的性能優(yōu)化效果也是非常好的。

廢話(huà)不多說(shuō),我們以事實(shí)說(shuō)話(huà)。大家看一下下面兩段程序,兩段程序的作用完全相同,就是將一個(gè)二維數(shù)組中的每一個(gè)元素做加1操作。大家看一下,覺(jué)得這兩段的程序是否會(huì)有性能差異?實(shí)際測(cè)試結(jié)果是兩者有近4倍的性能差異。

性能優(yōu)化,我們應(yīng)該知道的更多一點(diǎn)

性能差異的原因分析

大家考慮一下,為什么有如此之大的性能差異?結(jié)合代碼,我們看到兩段代碼的差異在于對(duì)數(shù)組元素的訪問(wèn)順序,前者是逐列訪問(wèn),而后者是逐行訪問(wèn)。結(jié)合圖1可能會(huì)理解的更加清楚一些。然后,我們?cè)诮Y(jié)合C語(yǔ)言中二維數(shù)據(jù)數(shù)據(jù)在內(nèi)存中的排布規(guī)則(可以在上述代碼中通過(guò)打印地址的方式驗(yàn)證一下),可以知道前者是訪問(wèn)連續(xù)的地址空間,而后者訪問(wèn)的是跳躍的地址空間。

性能優(yōu)化,我們應(yīng)該知道的更多一點(diǎn)

圖1 兩種訪問(wèn)形式

以整形數(shù)組為例,也就是說(shuō),前者訪問(wèn)的地址依次為X,X+4,X+8等等。而后者訪問(wèn)的地址則依次為X,X+4096,X+8192。后者每次跳躍4KB的地址空間。

了解了上述差異后,大家有沒(méi)有想到性能差異的原因?我們知道CPU為了提升訪問(wèn)內(nèi)存的性能,在其和內(nèi)存之間增加了緩存,現(xiàn)代CPU緩存通常為3級(jí)緩存,分別是L1、L2和L3,其中L1和L2是CPU核獨(dú)有的,而L3是同一顆CPU的多核共享的。其基本的架構(gòu)如圖2所示。

性能優(yōu)化,我們應(yīng)該知道的更多一點(diǎn)

圖2 CPU緩存架構(gòu)

由于緩存分布式的特點(diǎn),在多個(gè)CPU之間需要保證其一致性。扯遠(yuǎn)了,總之緩存需要切割為比較小的粒度進(jìn)行管理,這個(gè)小粒度的管理單元稱(chēng)為緩存行(可以類(lèi)比頁(yè)緩存中的緩存頁(yè))。由于緩存的容量遠(yuǎn)遠(yuǎn)小于內(nèi)存的容量,因此緩存無(wú)法把內(nèi)存中的內(nèi)容都加載其中。緩存能夠其作用的最主要的原因是利用的常規(guī)業(yè)務(wù)訪問(wèn)數(shù)據(jù)的兩個(gè)特性,也就是空間局部性和時(shí)間局部性。

  • 空間局部性:對(duì)于剛被訪問(wèn)的數(shù)據(jù),其相鄰的數(shù)據(jù)在將來(lái)被訪問(wèn)的概率高。
  • 時(shí)間局部性:對(duì)于剛被訪問(wèn)的數(shù)據(jù),其本身在將來(lái)被訪問(wèn)的概率高。

了解了上述原理,我們就知道,對(duì)于上面程序程序代碼,由于第二段程序依次跳躍的太遠(yuǎn),也就是不滿(mǎn)足空間局部性,從而導(dǎo)致緩存命中失敗。也就是說(shuō)第二段程序其實(shí)無(wú)法訪問(wèn)緩存中的數(shù)據(jù),而是直接訪問(wèn)的內(nèi)存。而內(nèi)存的訪問(wèn)性能要遠(yuǎn)遠(yuǎn)低于緩存的訪問(wèn)性能,因此就出現(xiàn)了文章一開(kāi)始的近4倍的性能差異。

關(guān)于程序性能的其它考慮

我們程序的很微小的改動(dòng)就有可能對(duì)性能產(chǎn)生非常大的影響。因此,我們?cè)谌粘i_(kāi)發(fā)中應(yīng)該處處注意代碼中是否有不恰當(dāng)?shù)拇a導(dǎo)致性能問(wèn)題。下面我們?cè)诹信e一個(gè)關(guān)于性能相關(guān)的程序?qū)嵗?,以便大家在以后的開(kāi)發(fā)中參考。

1. 程序結(jié)構(gòu)

不合理的程序結(jié)構(gòu)對(duì)性能的影響有的時(shí)候是災(zāi)難性的。下面兩個(gè)函數(shù)的性能差異在字符串很長(zhǎng)的情況下將非常巨大。函數(shù)lower1在每次循環(huán)中都計(jì)算一下字符串的長(zhǎng)度,而這種計(jì)算并不是必要的。函數(shù)lower2則是在循環(huán)開(kāi)始之前計(jì)算字符串長(zhǎng)度,而后通過(guò)一個(gè)恒定的變量來(lái)進(jìn)行條件判斷。問(wèn)題的根源在于strlen函數(shù),這個(gè)函數(shù)通過(guò)循環(huán)計(jì)算字符串的長(zhǎng)度,如果字符串比較長(zhǎng),那這個(gè)函數(shù)將相當(dāng)耗時(shí)。

性能優(yōu)化,我們應(yīng)該知道的更多一點(diǎn)

2. 過(guò)程(函數(shù))調(diào)用

我們知道在過(guò)程調(diào)用的時(shí)候會(huì)存在壓棧和出棧等操作,這些操作通常都是對(duì)內(nèi)存的操作,且過(guò)程比較復(fù)雜。也就是說(shuō),函數(shù)的調(diào)用過(guò)程是比較耗時(shí)的操作,盡量減少函數(shù)調(diào)用。

值得慶幸的是現(xiàn)代的編譯器可以對(duì)函數(shù)調(diào)用做很多優(yōu)化工作,簡(jiǎn)單的函數(shù)調(diào)用通??梢员痪幾g器優(yōu)化調(diào)。所謂優(yōu)化調(diào)是只在機(jī)器語(yǔ)言(匯編語(yǔ)言)層面已經(jīng)沒(méi)有高級(jí)語(yǔ)言的函數(shù)調(diào)用了。

我們通過(guò)一個(gè)具體的例子看一下,通過(guò)C語(yǔ)言實(shí)現(xiàn)一個(gè)簡(jiǎn)單的函數(shù)調(diào)用,其中函數(shù)fun_1調(diào)用函數(shù)fun_2,而函數(shù)fun_2又調(diào)用了printf。這里fun_2并沒(méi)有做什么太多的工作,只是將兩個(gè)參數(shù)相加后傳給printf。

性能優(yōu)化,我們應(yīng)該知道的更多一點(diǎn)

圖3 函數(shù)調(diào)用優(yōu)化

如圖所示,在gcc不做任何優(yōu)化的情況下,反匯編的代碼(圖3左下角)可以看出,整個(gè)邏輯非常清晰,只是按部就班的調(diào)用函數(shù)。但是,通過(guò)-O2優(yōu)化后,匯編代碼變得非常簡(jiǎn)潔了(圖3右下角),通過(guò)fun_1的匯編代碼可以看出它根本沒(méi)有調(diào)用fun_2,而是直接調(diào)用的printf函數(shù)。因此,在不影響其功能的情況下,編譯器是可以?xún)?yōu)化調(diào)函數(shù)調(diào)用的。但這不是絕對(duì)的,稍微復(fù)雜的函數(shù)調(diào)用編譯器可能就無(wú)能為力了,而此時(shí)就可能導(dǎo)致性能損耗。

3. 運(yùn)算符差異

不同的運(yùn)算的耗時(shí)差異也是非常巨大的,比如乘法的耗時(shí)是加法的兩三倍,而除法的耗時(shí)是加法的十倍以上。因此在訪問(wèn)頻度比較高的邏輯中減少除法的使用將會(huì)明顯的提升。

在Java的HashMap實(shí)現(xiàn)中,通過(guò)位運(yùn)算來(lái)計(jì)算哈希的Key,而不是通過(guò)模運(yùn)算。因?yàn)槟_\(yùn)算本身是除法運(yùn)算,性能要比位運(yùn)算差十倍以上。

  1. static final int hash(Object key) { 
  2.  int h; 
  3.  return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16); 

更詳細(xì)的處理邏輯請(qǐng)參考JDK的源代碼,本文僅僅是拋個(gè)磚 。

4. 引用與拷貝

支持類(lèi)的高級(jí)語(yǔ)言在傳遞對(duì)象參數(shù)的時(shí)候涉及拷貝的過(guò)程,對(duì)象的拷貝也是比較消耗性能的操作。當(dāng)然,高級(jí)語(yǔ)言通過(guò)一種成為引用的機(jī)制實(shí)現(xiàn)了對(duì)象地址的傳遞,這樣就避免了拷貝的過(guò)程(這就是傳值與傳址的差異)。

在程序開(kāi)發(fā)過(guò)程中關(guān)于性能的問(wèn)題還很多,本文無(wú)法一一列舉出來(lái)。但,關(guān)鍵的問(wèn)題是掌握技術(shù)的底層實(shí)現(xiàn)原理,任何其它高層的內(nèi)容都可以通過(guò)底層原理解釋的,正所謂萬(wàn)變不離其宗。

責(zé)任編輯:趙寧寧 來(lái)源: 今日頭條
相關(guān)推薦

2019-06-17 06:18:27

邊緣計(jì)算物聯(lián)網(wǎng)霧計(jì)算

2020-09-25 17:44:43

人工智能 倫敦時(shí)裝學(xué)院

2010-05-20 15:29:43

優(yōu)化IIS

2015-07-17 11:12:43

IOS搜索API

2015-07-21 16:43:13

IOSUI

2024-07-29 00:00:00

C程序色彩文本

2015-12-08 16:14:04

2023-12-25 07:56:23

Linux內(nèi)存管理內(nèi)存映射

2021-10-18 10:21:28

程序員技能優(yōu)化

2021-07-14 11:13:46

線程性能優(yōu)化阿里云

2024-07-11 08:26:00

2022-06-29 10:06:27

Webpack優(yōu)化技巧前端

2024-09-02 14:30:43

2012-03-27 08:49:19

Json

2009-09-14 19:44:27

LINQ To SQL

2009-07-09 15:09:05

JDK卸載

2017-09-07 15:12:42

程序員

2017-01-15 15:13:37

Android性能優(yōu)化優(yōu)化點(diǎn)

2023-12-29 08:29:15

QPS系統(tǒng)應(yīng)用

2025-05-29 00:00:00

UI 庫(kù)前端模塊化
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)