?
接上一篇:?
http://caoyaojun1988-163-com.iteye.com/blog/1302936
?
5 性能
雖然除了互斥鎖,同步框架也支持其他許多風(fēng)格的同步;但是鎖的性能是最容易比較和衡量的,即便如此,還有很多不同的測量方法。這里的實(shí)驗(yàn)旨在揭示開銷和吞吐量。在每項(xiàng)測試中,每個(gè)線程多次更新一個(gè)偽隨機(jī)數(shù),計(jì)算使用函數(shù):nextRandom(INT種子):
?
int t = (seed % 127773) * 16807 –(seed / 127773) * 2836; return (t > 0)? t : t + 0x7fffffff;
? 其中一組線程每次迭代更新的概率為S,他們共享一個(gè)互斥鎖下的生產(chǎn)器,另外一組線程使用無鎖的本地生產(chǎn)器;并且在線程競爭的時(shí)候短時(shí)間的鎖定區(qū)域,以減少其他因素的影響,使用隨機(jī)數(shù)函數(shù)有兩個(gè)方面的考慮,一是用于檢測是否被鎖定(它是一個(gè)很好生產(chǎn)器),二是讓循環(huán)內(nèi)的代碼不會讓JVM優(yōu)化掉。
?
我們比較了4種鎖:使用synchronized關(guān)鍵字的內(nèi)建鎖(Builtin)、在第4節(jié)演示的簡單的互斥(Mutex)類、使用ReentrantLock的重入鎖(Reentrant)、使用“公平”的模式的ReentrantLock的公平鎖。 所有的測試使用Sun J2SE1.5 JDK 的第46個(gè)build版本,選擇服務(wù)器模式;在正式搜集數(shù)據(jù)之前,跑20組數(shù)據(jù),以消除“預(yù)熱”的影響;測試的時(shí)候,除了公平模式只迭代運(yùn)行一百萬次,其他每個(gè)線程迭代運(yùn)行1000萬次,
測試機(jī)器使用四個(gè)基于x86的機(jī)器和四個(gè)基于UltraSPARC的機(jī)器。所有x86機(jī)器上運(yùn)行Linux RedHat2.4 NPTL的基代內(nèi)核和庫;所有的UltraSparc機(jī)器運(yùn)行Solaris9。所有的測試都是在系統(tǒng)最輕負(fù)載時(shí)進(jìn)行;測試機(jī)的其他方面沒有要求,因?yàn)橥耆幱陂e置狀態(tài);“4P”的名稱,其實(shí)表示是兩個(gè)超線程(hyperthreaded HT)Xeon的處理器,所以跟接近4核而不是2核。沒有任何人為的縮小分歧。如下所示,相對應(yīng)成本的同步器與處理器的個(gè)數(shù)、類型,速度并沒有一個(gè)簡單的關(guān)系。
?
5.1、負(fù)載
無競爭時(shí)的開銷,可以通過僅僅運(yùn)行一個(gè)線程,每次迭代用S=1的版本減去S=0的版本(不會去訪問共享變量)的時(shí)間;表2顯示了不同同步器的運(yùn)行情況,單位是納秒;Mutex類最接近測試框架的基本成本開銷。重入鎖(Reentrant )的額外開銷,表示記錄當(dāng)前所有者的線程和錯(cuò)誤檢查的開銷,公平鎖的額外開銷表示首先檢查隊(duì)列是否為空的開銷。
表2還顯示tryAcquire與使用“快速通道”--內(nèi)置鎖的成本。這里的差異主要反映了使用不同的原子操作和跨鎖、機(jī)器的內(nèi)存壁壘的成本。在多處理器時(shí)這些指標(biāo)往往完全高于其他的。內(nèi)置鎖與同步器的主要的區(qū)別顯然是由于Hotspot 的鎖在獲取鎖和解鎖都使用compareAndSet,而同步器的類只有在獲取使用compareAndSet,釋放的時(shí)候使用volatile 的寫(即,屏蔽多處理器的內(nèi)存屏障,和所有的處理器上的指令重排約束);
表3的場景是S=1、運(yùn)行256個(gè)并發(fā)線程,制造大量的鎖競爭,在完全飽和競爭的情況下,F(xiàn)IFO鎖比內(nèi)建鎖有更小的開銷(等價(jià)更大的吞吐量),并且比公平鎖少兩個(gè)數(shù)量級。這表明:高并發(fā)的情況下,允許闖入的FIFO的策略有更好的效率。
?
表3還顯示,即使有較低的內(nèi)部開銷,但是由于上下文切換的時(shí)間導(dǎo)致了公平鎖的較差的性能。上面的時(shí)間可以粗略的看到在各個(gè)不同平臺上阻塞、喚醒線程的比例;此外,一個(gè)后續(xù)的實(shí)驗(yàn)(只使用機(jī)器4P)顯示,公平性的設(shè)置對這些鎖的總體方差影響不大。可以作為一個(gè)較粗粒度的變化維度,就線程結(jié)束時(shí)間而言,在4P的機(jī)器上公平鎖(Fair)的標(biāo)準(zhǔn)差為0.7%,Reentrant的標(biāo)準(zhǔn)差為6.0%;作為對比,如果模擬長期持有鎖,一個(gè)方案是,每個(gè)線程獲取每個(gè)鎖的時(shí)候計(jì)算16K的隨機(jī)數(shù)
總運(yùn)行時(shí)間幾乎相同(公平鎖9.79s,Reentrant9.72s);公平模式獲取更小的標(biāo)準(zhǔn)差大約0.1%,而Reentrant 上升到29.5%。
5.2 吞吐
大多數(shù)的同步器使用時(shí)處于無爭和飽和競爭的極端之間。這可以沿著兩個(gè)維度去做實(shí)驗(yàn)和研究,一個(gè)是固定線程集合中線程的數(shù)量,改變發(fā)生競爭的概率,另一個(gè)是固定競爭的概率,增加線程集合中線程的數(shù)量。我們通過使用可重入鎖(Reentrant),在不同的競爭概率和線程數(shù)量的場景中運(yùn)行來說明這些因素的影響,下面是slowdown的計(jì)算方法:
? t表示總共執(zhí)行的時(shí)間, b是一個(gè)線程沒有競爭或者同步時(shí)的執(zhí)行時(shí)間,n是線程的數(shù)據(jù),p是處理器的數(shù)量,s任然表示訪問共享變量的概率;slowdown的值等于總時(shí)間除以最小的串行執(zhí)行的時(shí)間加上并行執(zhí)行的時(shí)間(這是理想情況);這是理想的時(shí)間模型,沒有任何同步開銷,因?yàn)闆]有任何線程與其他線程沖突而被阻塞。即便如此,在非常低的競爭下,一些測試結(jié)果可能比這個(gè)理想模型稍微好一些,,大概是由于jvm的優(yōu)化,流水線等引起細(xì)微的差別;
圖中所有的數(shù)字取2為低的對數(shù),例如:1.0表示測試的時(shí)間是理想模型的2倍;4.0表示16倍;使用對數(shù)是為了解除對基本時(shí)間的依賴,所以與使用基礎(chǔ)計(jì)算結(jié)果具有相同的趨勢;這些測試使用的競爭的概率從1/128(0.008)到1;間隔2的冪,線程數(shù)是從1到1024,間隔是2的冪的一半;
在單處理器(1P和1U)的情況在,隨著競爭的增加新能下降,但是跟線程的數(shù)量沒有關(guān)系。多處理器一般會看到更糟糕的下降速度。多處理器的圖形顯示,在很少線程的時(shí)候會出現(xiàn)一個(gè)峰值,然后迅速下降;這反映了性能的過渡區(qū),這個(gè)時(shí)候闖入的線程和被喚醒的線程同樣可能獲得鎖,產(chǎn)生競爭因此經(jīng)常迫使對方阻塞。在大多數(shù)情況下,在接下去就是平滑的區(qū)域,這個(gè)時(shí)候鎖幾乎永遠(yuǎn)不可用,導(dǎo)致跟單處理器的順序的模式類似;無論有多少個(gè)處理器的機(jī)器,都必然出現(xiàn)。 同樣還可以看到其他的信息;例如,全部有競爭的時(shí)候(概率為“1.000”)較少處理器的機(jī)器上slowdowns相對較差。
?
?
這些結(jié)果,可以發(fā)現(xiàn)如果調(diào)解阻塞(阻塞和喚醒)的支持方式去減少上下文切換和相關(guān)開銷的可以提供很小但是對此框架有明顯改善的性能。此外,可以使用其他形式的自適應(yīng)的自旋、針對多個(gè)處理器的高并發(fā)的鎖,可以避免這里看到的震動(dòng)。而自適應(yīng)自旋在不同的環(huán)境下工作往往是非常困難的,針對具體的應(yīng)用程序可以使用配置文件去配置使用基于這個(gè)框架的自定義的鎖。
6、總結(jié):
截止寫這篇文章的時(shí)候,java.util.concurrent中的同步框架還是很新的功能,還需要在實(shí)踐中去評估,在j2se 1.5 發(fā)布之前,它的設(shè)計(jì)、實(shí)現(xiàn)、性能都是不可預(yù)知的;無論如何,框架的出現(xiàn)成功的滿足可以基礎(chǔ)它高效創(chuàng)建新的同步器的目標(biāo)。
?