JVM知識在離線資料中的運用

程式設計一生發表於2017-04-12

  又是飛花的季節了。多愁善感的林妹妹看到柳絮說:“嫁與東風春不管,憑爾去,忍淹留。”寶姐姐看了卻來一句:“好風憑藉力送我上青雲”。

  特別羨慕情商高的人,經常在想他們是怎麼做到的。從來看不出他們不喜歡誰,滿眼裡都是真誠。漸漸的開始能夠理解所有的人。比如:有些女孩愛化很濃的妝,後來才想到不是所有的人都天生皮膚細,清水洗把臉就可以出門。現實的女孩大都是夢碎之後被碎片扎的遍體鱗傷,更應該被呵護才是。愛錢是因為不是所有的人都有不依靠別人就能活的能力,誰最先想到的不是衣食住行呢。但我還是理解不了浪費糧食的,不管是植物還是動物,為了我付出了自己的生命,我好歹也應該讓它成為我身體的一部分,和它一起好好的活著~~

  我是一個心想事成的人,人生少走了很多彎路,少了很多思考,也少了很多對他人的理解。還好大腦的自動補全能力比較強。在超市裡,我走到酒的那一排都會繞著走,因為總是感覺酒瓶子會掉下來碎掉。有次看《神盾局特工》看完了換一下節目才發現靜音了。因為之前看過好幾集了,看到字幕大腦裡自動把聲音補上了,竟然沒發現。不知道這個能力和語言天賦之間有沒有什麼聯絡。但是我的大腦會儲存很多的聲音,很少儲存影像。很少真正很關心一個人的長相。對於我,一個有磁性聲音的人會更有魅力。不知道這個和寫不好字的缺陷之間有沒有什麼聯絡[衰]。小鮮肉的這種能力在他一歲的時候就體現出來了。一個媽媽推著一個寶寶在前面走,他看到小推車上的水壺有一半在外面往下沉。他就大喊:要掉出來了,要掉出來了。別人沒怎麼樣,他急得不行了。

  心想事成是一種性格,而不是能力。小鮮肉如果有想做的事兒,想要的東西,他很少直接說。他會非要別人去猜他怎麼想的。我卻總是想辦法讓他自己說出來,因為這樣的一種做事方式,他會終生受益的。比如說:俞伯牙如果是我這樣的性格,來了一個人,不管是誰,他在彈琴,他就會說:我彈的高山,我彈的是流水。也就不會“知音難覓”一說了。這樣的人因為少了讓別人去理解自己這一步,所以更多會考慮怎麼理解別人。這樣的人還很單純,單純的人臉上會獨有一種“笑起來很甜”。

  《小王子》裡的小主人公整個人生都在探索自己為什麼會愛上那朵玫瑰。那花兒長的美,卻矯情,虛榮,帶給了他無盡的痛苦。最後受到了小狐狸的啟發才發現:那花兒的獨一無二在於他對花兒的付出,花兒對自己的馴服。其實哪有那麼糾結?愛了就愛了唄。

  在現實中,會是這樣一種情況。兩個男孩喜歡同一個女孩子。其中一個男孩總是在想:“我擁有什麼資本能讓她對我不離不棄呢,我有沒有比另一個男孩更優秀,如果她看清楚了真實的我會不會不喜歡我?我的付出會不會一無所獲?她是不是一個好女孩?”另一個男孩只在想一件事,那就是我喜歡那個女孩子我要讓她知道。一個夠聰明的女孩子就算心裡喜歡的前一個,無論理智還是情感,她也不會選他(碰上我這種愛給自己找麻煩的人另當別論[汗])。因為這樣人的性格產生的連鎖反應是:總是在權衡利弊,人會越來越自私,自我為中心,不願意付出。想的太多,做的太少,害怕承擔後果,這樣的人根本沒有真心去愛一個人的基本能力。而後一個男孩:想到就去做了,他會想各種方法去達到目的,做了很多,承擔了很多,會更有擔當和責任心。為啥我會想這些呢?好歹我們也是中科院心理學的研究生,不能白學啊!

  一定要相信周圍的人都是很聰明的,自己是什麼樣的人,別人都是可以看出來的,所以也沒有什麼必要藏著掖著的。想了很多,也總有自己沒有考慮到的因素。谷歌的對弈軟體也不能百分百分取勝。所以,只要去做自己想做的事兒就可以了,想多想少,結果可能沒有那麼大的差別,失之東隅收之桑榆。做和不做,區別可就大了。

  小狐狸對小王子說:“如果你馴服了我,我的生命就會充滿陽光……我不吃麵包,麥子對我本沒有什麼意義,麥田更不會讓我產生聯想,可一旦你馴服了我,一切都改變了,因為你有金色的頭髮,再看到麥田我就會想起你,而且我還會喜歡傾聽風吹滿麥浪的聲音……” 小狐狸忍受著最終會哭一場的後果讓小王子馴服了自己。最終小王子選擇了回去找自己的玫瑰。但是小狐狸的生命從此鮮活起來,一切都有了意義。

  額~~,說多了。在想離線資料這個專案的獨特之處在哪裡。它用到了很多和JVM打交道的地方,順便將這個總結一下。

  我既然把記憶體引數配置設定成了這個樣子。我當然要知道這麼龐大的資源都幹了啥。特別是半夜跑全量的時候,我有次測試了一晚上,第二天早上睡覺中午醒來發現那臺機器登入不了了。找運維,他們也登入不了,最後只好重啟了伺服器。我分析發現新生代設定的不合適,導致它沒有空間進行full gc。結果記憶體全滿了。最喜歡做這樣的專案了,用現成的框架,程式會死,把機器弄死很不容易的[偷笑]

  首先說我們線上JVM用的Hotspot,因為是64位機器,只支援server模式的。使用預設的JIT編譯器模式。Java7。因為在java8中移除了永久代,犧牲了一點效能來獲取更高的安全保障。但這個程式是個後臺服務,升級java8反而不合適了。

  處理資料物件特別大,有的壓縮前30多M。因為搜尋哥哥們規定實時訊息一個專輯下要包含所有的視訊,有的專輯下面有幾萬個視訊[哭笑]。所以在處理這一條資料的時候,處理完的部分仍在記憶體中。為了可維護,晚上全量推送和其他時段的實時推送資料處理部分邏輯共用。晚上全量是用50個執行緒的執行緒池來跑的。如果50個執行緒內部序列,雖然我做了策略,分派處理內容的時候,將超大的專輯獨立出來。一個執行緒處理幾百個小專輯,但是大專輯只處理兩三個。但是一個專輯就要十幾分鍾。但是專輯的分為多個區域,多種語言的,每種都要獨立成一條資料,全量檔案專輯我定義了共440個執行緒,每個執行緒獨立壓縮生成一個檔案,增量時發訊息也是扔到MQ裡不用管。這些不需要通訊的地方完全可以非同步處理。非同步又涉及到總是新建執行緒的堆回收問題。所以我將這些執行緒類都放到了物件池裡進行管理。但是全量的時候的堆佔用還是很大很大的,Full GC也很頻繁。空間換時間嘛,所以JVM引數配的看起來很誇張,但真不是浪費。專輯的資料量是十萬級,視訊的資料量是千萬級。原來的離線推送系統只傳送ID給搜尋那邊,跑全量也要4個小時。所以之前是一週跑一次全量。我做的新系統,全量生成的專輯共15個G,視訊佔31個G。專輯和視訊跑完全量一臺用20多分鐘,另一臺長一些(因為另一臺的資料庫的機器不是同一執行商,時間開銷在網路上),現在我們是一天一個全量。

  -Xss這個引數的最終設定,我當時是整晚沒睡覺測試的。因為這個引數是每個執行緒的堆疊大小。是方法執行的記憶體區,每個方法執行時會在虛擬機器棧中建立棧幀。設定的小,跑起來會慢,設定的大,跑起來快,CPU計算速度就上去了。這裡面還涉及到了虛擬機器的逃逸分析,可能引起CPU跑滿。說到這裡我是不是還得說說虛擬機器棧幀的結構啊。

棧幀(Stack Frame)結構

棧幀是用於支援虛擬機器進行方法執行的資料結構,是屬性執行時資料區的虛擬機器站的棧元素。棧幀包括:

1>區域性變數表(locals大小,編譯期確定),一組變數儲存空間,容量以slot為最小單位。

2>操作棧(stack大小,編譯期確定),操作棧元素的資料型別必須與位元組碼指令序列嚴格匹配。

3>動態連結,指向執行時常量池中該棧幀所屬方法的引用,為了動態連線使用。

  前面是靜態解析

  對於執行期轉化為直接引用,是動態解析

4>方法返回地址。

  正常退出:執行引擎遇到方法返回的位元組碼,將返回值傳遞給呼叫者

  異常退出:遇到Exception沒被捕獲時沒有返回值

5>額外附加資訊:由具體虛擬機器實現。

說到這裡我是不是還應該畫一張java的記憶體模型啊。大體是這個樣子的:

 

  在這個地方想起來一個習慣,就是我用的整合開發環境是Eclipse,喜歡用它因為它是純java寫的。而且我經常把它搞死。每次把它弄死了我都會很認真的去分析它死掉的原因。對深入瞭解jvm很有幫助。

 

  有必要貼一下垃圾收集日誌。這是線上比較老的GC日誌。因為我已經把列印gc日誌這個選項關閉很久了。大家可能注意到了我的新生代設定的特別大,37g。這不僅僅是因為測試時伺服器掛過。而是我說了,處理的資料物件特別大,這些物件都是朝生暮死的。如果新生代設定的不夠大,這些大物件就會直接進入老年代,大大降低了垃圾回收的效率。大家也可以看出來,對新生代的垃圾回收是相當有成效的,99%都被回收了。

  這裡介紹一下資料結構中的棧和堆與記憶體分配中的棧和堆:

  資料結構中的棧是一種後進先出性質的資料結構,像一個桶。取資料不能像陣列那樣想取哪個取哪個。必須先把想取的資料之後進來的資料全pop出去。

  資料結構中的堆通常指二叉堆。分為最大堆和最小堆(我還用這個資料結構實現一種加密機制獲得了專利)。它的存取就要比棧靈活。

  如果是C++出身的程式設計師對於記憶體分配的棧和堆理解就完全不是問題。因為java就是c++寫的。記憶體中的棧區處理相對較高的地址以地址,不斷的分配,分配的地址增大。棧地址是相反的。所以在c++語言中和jvm中,棧都是系統自動分配空間的,速度快。而堆是需要申請的,我記得是malloc函式。棧上的資料的生存週期是在函式的執行過程中,執行後就釋放掉,不可以再訪問。堆上的資料只要程式設計師不釋放空間,就一直可以訪問到。這就是為什麼java棧是執行緒隔離的,而堆是執行緒共享的。

如需轉載,請註上我的原文連結: http://www.cnblogs.com/xiexj/p/6700747.html  謝謝哦~~

相關文章