2010年8月27日 星期五

NUC501-虛擬記憶體問題的最終回

上回出現RAM虛擬記憶體效能差勁,卻不知原因為何的謎團後,經過詳細的(?好啦!我承認是亂槍打鳥的)檢查、抽絲剝繭,測試各相關軟體元件的執行效能,造成效能瓶頸的犯人終於找到了!原來犯人就是「帕雷拖法則」!

根據維基百科記載,帕雷拖法則是:

帕雷托法則(Pareto principle),也稱為80/20法則,此法則指在眾多現象中,80%的結果取決於20%的原因...在電腦科學裡,帕雷托法則可藉由觀察80%的資源是由20%所操作使用,來最佳化資源。在軟體工程上,常有接近90%的電腦程式執行次數花費在10%的程式原始碼執行。

而在這個專案中,效能低落的發生與程式撰寫方式有很大的關係。由於專案開發的時候,常喜歡將使用到的功能,寫成群組型態的功能區塊。例如有專門處理LCD顯示的gfx系統、處理文字顯示的font系統,以及處理檔案系統的APSLib等等。而各功能區塊又會進行細分,有時會製造出許多單一功能的小函式。

之後為了避免上層程式執行功能時,都得要呼一堆小函式,所以又建立easy系列的函式,比方說EasyOpenFile之類的,這樣想要很輕鬆愉快的寫上層程式,就用easy系列,想要easy系列之外的低階控制就另外自己呼小函式。當同樣的低階控制程式碼多了起來,就又會為它增加了一個easy函式。上層程式寫好以後,它的上上層程式大多會形成任務分派形式的程式碼(dispatcher),因此完成版的程式碼很有大腸包小腸的Fu。大金每次看我的程式,都說我的主程式看起來簡單到不行(因為只是任務分派的迴圈而已),可是副程式卻呼來呼去複雜到死。

不過這種寫法是以前教科書上的建議(相信有很多程式設計師也是這麼做),這麼多年下來執行也都沒什麼大問題呀!為何這次會踢到鐵板呢?

主因是:這種程式寫法不適用在目前所設計的虛擬記憶體架構!

比方說,執行主程式時,會因為主程式本身是任務分派的形式,又因底下程式細分的關係,造成虛擬記憶體得從各個不同的區塊載入這些細分的程式,程式層數愈深,頁面切換的次數愈多,最後頁面也許就全部被這些程式碼佔據。當返回主程式時,主程式早已從頁面中消失,這時虛擬記憶體必須將主程式切換回來,如果主程式是迴圈構成的,又得繼續進行上述的處理。

發現問題的所在了嗎?問題就在於主程式(及各功能的頂層程式)本身所需的CPU時間幾乎不到1%,卻要勞師動眾將它從SpiROM複製到虛擬記憶體頁面上,然後才執行不到幾個指令,又被置換出去!所以當程式像洋蔥一樣,一層包一層,層級愈高的程式碼愈會形成任務分派形式的情況下,CPU的效能就被這些執行時間不到1%的程式碼給消耗掉了!那該怎麼辦呢?

一個方法是打掉重寫,用inline的方式執行函式,這樣會使得虛擬記憶體頁面切換有點像是循序進行,減少效能大起大落的問題,但程式碼編譯出來會非常巨大,這對大金想用小容量的SpiROM是完全不可行。

另外一個方法,則是多年前看的文章所引發的靈感。文章內容是探討PowerPC晶片的cache lock指令,對於多媒體處理的影響。由於多媒體資料大多為一次性且大量,如果沒有執行cache lock,將多媒體處理用的程式碼鎖定在快取內,很快的,CPU的快取便會充斥這些一次性的多媒體資料,而造成多媒體處理的效能低落!除此之外,Apple的麥金塔電腦,從68K系列的CPU轉換到PowerPC時,也是透過cache lock的方法來提昇68K模擬器的執行效率。之前研究NDS時,許多遊戲程式要播放即時影片前,都會透過NDS CPU的cache lock功能把處理程式鎖在快取內,以提昇播放的順暢度。這讓我想到,應該把這個虛擬記憶體系統當成快取系統來看待,才能在寶貴的RAM中放需要提昇速度的程式碼,而不是那些任務分派用的程式!

原先想在虛擬記憶體系統放個旗標,代表lock,這樣虛擬記憶體切換頁面時,就忽略這個頁面,頁面的鎖定就由想要留在頁面的程式碼主動進行lock好了。但一想到必須在各個系統放CacheLock及CacheUnlock之類的函式就有點暈了,再加上大腸包小腸形式的程式碼,還得要小心不能把所有頁面都lock(其它程式就不能執行了),其複雜度光想就腦袋打結了。

在反覆思考實作的方法卡了好久,只好試著反向思考,以結果來說,我們希望這些執行時間1%以下的程式碼,不要進入虛擬記憶體頁面執行,那NUC501有什麼硬體能達成呢?突然想到答案就是之前虛擬記憶體亟欲取代的SpiROM!雖然SpiROM速度不快,但能夠執行程式呀,跑這些任務分派的程式碼應該夠了!

趕忙修改ld的設定檔,增加一個NONCACHE的程式節區,而區段就在SpiROM所在的0x40000000位址上,緊鄰可被載入虛擬記憶體的程式碼之後(因為這些程式碼本身仍需要SpiROM當載體),這樣連虛擬記憶體系統都不用增加旗標什麼的,直接就能自由呼叫分散在虛擬記憶體與SpiROM上的副函式!

接下來的工作就比較麻煩,必須挑出哪個函式是屬於任務分派類型的程式碼,但排除performance senstive的函式,挑出來之後,便為它們標上NONCACHE巨集,這樣在編譯時,這些函式會自動被安排到NONCACHE節區中,屬於最大的任務分派函式main()也不例外!在編譯完成後,我緊張的把程式碼燒到開發版上測試。

結果效能提昇的數字令人驚訝,原先APSLib令人難堪的12K低速,效能一整個提昇26倍,得到312KB的讀取速度,字型顯示的處理時間也低於1秒了,雖然仍比原生讀取速度低,但已經足夠,只要專案完成時效能不是太低,我想應該不會再改進這個部份了。

那麼有關探討NUC501上虛擬記憶體實作的問題,應該就在這篇結束了。如果有在看這個網誌的朋友,也歡迎提出您的見解與問題,一起討論哦!

2010年8月16日 星期一

香港自由行之日景太平山-下

由於來到香港的第一天與第二天都沒能去太平山看夜景,但纜車與觀景台套票已經買了,也不能退,所以只好在晚上回台灣前,去太平山看一下日景囉!

原本想照第一天的方式,先坐港鐵到金鐘站然後再走路去纜車站,卻突然撇見旅行社給的城市大巴旅遊兌換券還沒用(原本想丟了),且城市大巴的港島旅遊路線有經過纜車站!雖然移動時間變長,至少不用走路,也可多一個大巴體驗,便立即改變行程,先坐港鐵到香港站,然後走到中環碼頭去換大巴票!

不過天氣不好,烏雲密佈,真希望不要下雨才好。



出了香港站之後,便遵行路線指示,經過空橋前往中環碼頭。香港真是處處高樓林立呀!



除了高樓以外,香港也處處建築工事中。



走了約10分鐘後,抵達中環碼頭,城市大巴已經在那裡等客人上門了。跟車掌換票後,就坐在大巴內吹冷氣等其他客人。



車子開動後,便登上大巴的二樓開始遊車河,欣賞香港的風光啦!







天空有些飄雨,但還好是小小地,希望不要像第一天的情況就好了。



城市叢林



欣賞著沿途的風光,不知不覺纜車站就到了,趕忙從二樓衝下去,告訴司機要下車。



突然看見第一天躲雨停車場對面的大樓,原來只差幾公尺就到纜車站了~~



排隊換完纜車票之後,跟著人群等纜車到站。



到達山頂之後,會經過一個賣許多貨品的山頂市集,吸引許多遊客駐足。











在這裡還有郵局,可以讓你買明信片寄給你的朋友與家人。



沿著路標走



搭乘手扶梯前往觀景台,沿途有許多在賣電器產品跟玩具的店家,蠻奇怪的。



由於有團員想上廁所,所以在這家店前等了一下,不知道好不好吃呢?



終於抵達山頂觀景台,觀景台的四面都可以看到不同的風景。雖然日景也蠻漂亮的,但還是想著如果是夜景該多好呢~~



















在觀景台待了半小時,愈來愈熱,便下樓去看杜莎夫人蠟像館。



瀏覽完太平山如果想去迪士尼,樓下的城堡型區域就是迪士尼的售票處了!真是方便。



來到樓下,就能看到粉貴的杜莎夫人蠟像館(其實就在山頂市集旁),一個人要160元港幣。



由於熱門的蠟像都有粉絲等著照相,所以我只好挑沒人合照的拍。不過蠟像館裡不是每個蠟像都可以拍,有些只能由內部的工作人員幫你拍,然後再到出口處付錢買相片~~



































欣賞完蠟像館之後,便趕忙坐大巴回中環碼頭,然後再坐港鐵回奧運站拿行李,準備坐接駁車到機場。



在落日餘暉中等待登機,香港機場除了有提供上網機可以使用以外,還有PS3可以玩!







這次到香港當導遊可以說是蠻失敗的,除了沒吃到正宗港式燒臘(原本買來做宵夜的廣東粥也被人吃掉,還一直跟我說好吃),行程動線也很差勁,雖然團員說還不錯玩,但本人是蠻後悔的,因為我直到要回家的第三天才開始抓到行程規劃的要訣啦~~





2010年8月12日 星期四

香港自由行之熱斃迪士尼-中

經過第一天的算是失敗行程之後,第二天的行程簡單許多,那就是整天都待在迪士尼,同行的團員建議依照網路上的流程來走。因此第二天一大早就得起床,要趕在迪士尼開門前先在門外拍照,等到迪士尼開門之後,就直接先衝到最裡面玩,因為這時大家都在外面逛,裡面的設施都不用排隊。等到人潮抵達後,再從裡面玩出去,這樣就可以避開洶湧的人潮!相當不錯的建議,就決定這樣進行。


第二天清晨起來,向窗外照一張,對比前晚的夜景照片。



抵達港鐵奧運站之後,需要先搭東涌線前往欣澳站,然後轉乘迪士尼線即可抵達,是這三天行程中最簡單的一天。



來了來了,傳說中的迪士尼列車終於來了。



連車中的吊環都是米奇的圖樣。



到站了,大家一哄而散。



迪士尼站的風格還蠻童話夢幻的,如果不想爬階梯上去的話,旁邊也有電動手扶梯可以搭乘。



終於來到迪士尼了,可是天氣真是熱到爆了!



經過了長長的大道之後...


就有噴水鯨魚加米奇衝浪可以看,這邊有很多遊客拍照。










再往前走就是迪士尼的大門了,這邊會進行背包的檢查,確定你沒有帶外食進去!因為裡面賣的食物很貴,相信很多人會決定自己帶。但檢查也不是很嚴格啦,把食物藏在包包內的衣服底下,檢查人員也不會動手翻。



準備排隊受檢



終於進來啦!大大的米奇正在歡迎著你!



剛好遇到遊園火車抵站



嗯,如果不要那麼熱更好!



美國小鎮一景,不過因為趕著到裡面去所以沒照太多。



第一個玩的設施「太空山」,果然完全不用排隊。類似九族文化村的太空山,不過特效更棒,時間更久,左甩右甩上下甩全部都有,還有180度的天幕投影加上雷射特效,更添臨場感。



「溼」了焦的疤撕光黏正在進行任務簡介,坐完太空山之後脖子被甩得快斷了!



出來之後繼續往下走,遇到怎樣都不肯往我這邊看的唐老鴨在玩泡泡。



發現前方有座城堡



原來是小小世界來的~~



城堡本身是個大鐘,會發出響亮的滴答聲。每15分鐘會報時,裡面的小小兵們會出來遊行!







可愛造型的路燈




等待報時的同時,吃吃看傳說中的士多啤梨+凡尼拉口味的冰淇淋。餅皮是現烤的又香又脆,冰淇淋也很好吃,不過這二球要港幣35元!實在有點貴。



時間一到,小小兵出來報時了!





進入小小世界之後,迎面而來就是超強的冷氣!小小世界跟我們這裡的小人國一樣,都是坐以流水為動力的船來瀏覽整個世界。對比外面的酷熱,這裡真是又涼又舒服的像天堂,結束時真是不想出去外面了!



小小世界裡面劃分五大洲,各有不同的風情,也用不同的感覺唱著小小世界的歌。



像印地安人就有自己的旋律,但基本上還是小小世界。



小美人魚(港譯:小魚仙)也來參一腳,整個就像快被淹死般,用咕嚕咕嚕的聲音唱著小小世界。



看完小小世界,也差不多午飯時間,剛好遇到遊行表演。



穿著腳後跟是滑輪鞋子的表演者,搭配好聽的歌曲。



吃完午餐後,又再次去小小世界吹冷氣,結果剛好錯過潑水遊行,只好匆匆帶過。之後又去欣賞米奇歌舞表演,因為不能照相,所以...



看完華麗又涼爽的歌舞表演後,又回到酷熱的街道上,之後一行人便待在拍照公園納涼,動都不動了。



終於有人提議要回飯店了,但因為我們的套票裡含一餐的費用,所以離開之前要用掉!我點的是紅燒雞肉燴飯(詳細的名稱忘了),口味還不錯,但飯跟前一日的咖哩有得拼,都很硬!



在充滿異國風情的帳篷餐廳用餐。



準備搭乘遊園火車前往大門。



此時天色已暗,美國小鎮有著不同的風情!























噴水鯨魚在燈光陪襯下更增添夢幻氣息。















連街燈都散發著不思議的感覺。



此時晚風吹起,一掃白日酷暑的感覺,原來迪士尼應該買星光票來才對。



由於夏日天黑的時間比較晚,煙火改到晚上九點,沒法待到那麼晚的我們只好先行離開了。















再會囉!下次來迪士尼應該要去東京的吧,哈哈~~