㈠ JVM垃圾回收的「三色標記演算法」實現,內容太干
三色標記法是一種垃圾回收法,它可以讓JVM不發生或僅短時間發生STW(Stop The World),從而達到清除JVM內存垃圾的目的。JVM中的 CMS、G1垃圾回收器 所使用垃圾回收演算法即為三色標記法。
三色標記法將對象的顏色分為了黑、灰、白,三種顏色。
白色 :該對象沒有被標記過。(對象垃圾)
灰色 :該對象已經被標記過了,但該對象下的屬性沒有全被標記完。(GC需要從此對象中去尋找垃圾)
黑色 :該對象已經被標記過了,且該對象下的屬性也全部都被標記過了。(程序所需要的對象)
從我們main方法的根對象(JVM中稱為GC Root)開始沿著他們的對象向下查找,用黑灰白的規則,標記出所有跟GC Root相連接的對象,掃描一遍結束後,一般需要進行一次短暫的STW(Stop The World),再次進行掃描,此時因為黑色對象的屬性都也已經被標記過了,所以只需找出灰色對象並順著繼續往下標記(且因為大部分的標記工作已經在第一次並發的時候發生了,所以灰色對象數量會很少,標記時間也會短很多), 此時程序繼續執行,GC線程掃描所有的內存,找出掃描之後依舊被標記為白色的對象(垃圾),清除。
具體流程:
在JVM虛擬機中有兩種常見垃圾回收器使用了該演算法:CMS(Concurrent Mark Sweep)、G1(Garbage First) ,為了解決三色標記法對對象漏標問題各自有各自的法:
CMS(Concurrent Mark Sweep)收集器是一種以獲取最短回收停頓時間為目標的收集器。目前很大一部分的Java應用集中在互聯網網站或者基於瀏覽器的B/S系統的服務端上,這類應用通常都會較為關注服務的響應速度,希望系統停頓時間盡可能短,以給用戶帶來良好的交互體驗。CMS收集器就非常符合這類應用的需求(但是實際由於某些問題,很少有使用CMS作為主要垃圾回收器的)。
從名字(包含「Mark Sweep」)上就可以看出CMS收集器是基於標記-清除演算法實現的,它的運作過程相對於前面幾種收集器來說要更復雜一些,整個過程分為四個步驟,包括:1)初始標記(CMS initial mark) 2)並發標記(CMS concurrent mark) 3)重新標記(CMS remark) 4)並發清除(CMS concurrent sweep)
其中初始標記、重新標記這兩個步驟仍然需要「Stop The World」。初始標記僅僅只是標記一下GCRoots能直接關聯到的對象,速度很快;
並發標記階段就是從GC Roots的直接關聯對象開始遍歷整個對象圖的過程,這個過程耗時較長但是不需要停頓用戶線程,可以與垃圾收集線程一起並發運行;
重新標記階段則是為了修正並發標記期間,因用戶程序繼續運作而導致標記產生變動的那一部分對象的標記記錄,這個階段的停頓時間通常會比初始標記階段稍長一些,但也遠比並發標記階段的時間短;
最後是並發清除階段,清理刪除掉標記階段判斷的已經死亡的對象,由於不需要移動存活對象,所以這個階段也是可以與用戶線程同時並發的。由於在整個過程中耗時最長的並發標記和並發清除階段中,垃圾收集器線程都可以與用戶線程一起工作,所以從總體上來說,CMS收集器的內存回收過程是與用戶線程一起並發執行的。
在應對漏標問題時,CMS使用了增量更新(Increment Update)方法來做:
在一個未被標記的對象(白色對象)被重新引用後, 引用它的對象若為黑色則要變成灰色,在下次二次標記時讓GC線程繼續標記它的屬性對象 。
但是就算是這樣,其仍然是存在漏標的問題:
G1(Garbage First)物理內存不再分代,而是由一塊一塊的Region組成,但是邏輯分代仍然存在。G1不再堅持固定大小以及固定數量的分代區域劃分,而是把連續的Java堆劃分為多個大小相等的獨立區域(Region),每一個Region都可以根據需要,扮演新生代的Eden空間、Survivor空間,或者老年代空間。收集器能夠對扮演不同角色的Region採用不同的策略去處理,這樣無論是新創建的對象還是已經存活了一段時間、熬過多次收集的舊對象都能獲取很好的收集效果。
Region中還有一類特殊的Humongous區域,專門用來存儲大對象。G1認為只要大小超過了一個Region容量一半的對象即可判定為大對象。每個Region的大小可以通過參數-XX:G1HeapRegionSize設定,取值范圍為1MB~32MB,且應為2的N次冪。而對於那些超過了整個Region容量的超級大對象,將會被存放在N個連續的Humongous Region之中,G1的大多數行為都把Humongous Region作為老年代的一部分來進行看待,如圖所示
Card Table(多種垃圾回收器均具備)
RSet(Remembered Set)
是輔助GC過程的一種結構,典型的空間換時間工具,和Card Table有些類似。
後面說到的CSet(Collection Set)也是輔助GC的,它記錄了GC要收集的Region集合,集合里的Region可以是任意年代的。
在GC的時候,對於old->young和old->old的跨代對象引用,只要掃描對應的CSet中的RSet即可。邏輯上說每個Region都有一個RSet,RSet記錄了其他Region中的對象引用本Region中對象的關系,屬於points-into結構(誰引用了我的對象)。
而Card Table則是一種points-out(我引用了誰的對象)的結構,每個Card 覆蓋一定范圍的Heap(一般為512Bytes)。G1的RSet是在Card Table的基礎上實現的:每個Region會記錄下別的Region有指向自己的指針,並標記這些指針分別在哪些Card的范圍內。這個RSet其實是一個Hash Table,Key是別的Region的起始地址,Value是一個集合,裡面的元素是Card Table的Index。每個Region中都有一個RSet,記錄其他Region到本Region的引用信息;使得垃圾回收器不需要掃描整個堆找到誰引用當前分區中的對象,只需要掃描RSet即可。
CSet(Collection Set)
一組可被回收的分區Region的集合, 是多個對象的集合內存區域。
新生代與老年代的比例
5% - 60%,一般不使用手工指定,因為這是G1預測停頓時間的基準,這地方簡要說明一下,G1可以指定一個預期的停頓時間,然後G1會根據你設定的時間來動態調整年輕代的比例,例如時間長,就將年輕代比例調小,讓YGC盡早行。
SATB(Snapshot At The Beginning), 在應對漏標問題時,G1使用了SATB方法來做,具體流程:
因為SATB在重新標記環節只需要去重新掃描那些被推到堆棧中的引用,並配合Rset來判斷當前對象是否被引用來進行回收;
並且在最後G1並不會選擇回收所有垃圾對象,而是根據Region的垃圾多少來判斷與預估回收價值(指回收的垃圾與回收的STW時間的一個預估值),將一個或者多個Region放到CSet中,最後將這些Region中的存活對象壓縮並復制到新的Region中,清空原來的Region。
會,當內存滿了的時候就會進行Full GC;且JDK10之前的Full GC,為單線程的,所以使用G1需要避免Full GC的產生。
解決方案:
㈡ 數控程序增量的演算法
確定轉速前要根據工件材料性質以及刀具能承受的最小最大切削速度,(數控刀具一般都有表明最大切削速度),車加工時的剛度、吃刀深度,冷卻情況等,先定下線速度(即切削速度),然後根據工件直徑大小,車製件類型,即外圓、鏜孔、切斷等,計算出每分鍾轉速。當然還要考慮機床承受能力。一般國產刀具YW1或YT15粗車時60~80米左右,精車時100~120米,進口刀具200米左右,當然還得綜合考慮刀具耐用度與經濟成本的關系,有些刀具安裝、對刀相當困難,取相對低速反而效率高。
F的演算法簡單得多,一般數控車床用G99比較容易控製表面粗糙度,粗車時0.2~0.4,精車時0.05~0.1,粗糙度與轉速也有很大關系,當然也要綜合考慮其它因素,萬不可死搬教條。
一名合格車工,要經常根據切削速度等計算車床轉速,以求得最大效益。
㈢ 什麼是增量式PID演算法
1,PID增量式演算法:是PID控制演算法的一種,有濾波的選擇,系統的動態過程加速的功能。
(1)濾波的選擇:可以對輸入加一個前置濾波器,使得進入控制演算法的給定值不突變,而是有一定慣性延遲的緩變數。
(2)系統的動態過程加速:如果被控量繼續偏離給定值,則這兩項符號相同,而當被控量向給定值方向變化時,則這兩項的符號相反。由於這一性質,當被控量接近給定值的時候,反號的比例作用阻礙了積分作用,因而避免了積分超調以及隨之帶來的振盪,這顯然是有利於控制的。但如果被控量遠未接近給定值,僅剛開始向給定值變化時,由於比例和積分反向,將會減慢控制過程。
2,PID增量演算法的飽和作用及其抑制:在PID增量演算法中,由於執行元件本身是機械或物理的積分儲存單元,如果給定值發生突變時,由演算法的比例部分和微分部分計算出的控制增量可能比較大,如果該值超過了執行元件所允許的最大限度,那麼實際上執行的控制增量將時受到限制時的值,多餘的部分將丟失,將使系統的動態過程變長,因此,需要採取一定的措施改善這種情況。