2014年2月18日 星期二

【Java】Make your object work better/fast...???

 That is my first English Blog post. And ,if you like to know, I never spend a day in school of Computer Science. So..... everything in this blog are amateur.
What is the different between those class???

If I use a loop to run a "new()" ... like new Test1(), or new Test2()... 100000 times, there are how much time they took to finish the loop.

Test1 :100 millisecond.
Test2:12000 millisecond.
Test3:34000 millisecond.

Obviously, more field the object has, more time it take to "new."

Is there more? Am I satisfied my own curiosity?

No! There is one more.


....... Interesting. They take the same time to finish the loop.

So the field make different, but method do nothing.



Wait!!!  There are more story about what happen when I use a infinity loop to test how many Test1/Test2/Test3 can a ArralyList<Test0> carry.......

Good night... it is 12 pm in Taiwan.

【Java】這樣設計物件有差喔!

差在哪裡?

我同樣用迴圈的方式放大其中的差異...在迴圈中執行「宣告動作」,──簡單來說,就是用類別 new 一個物件出來啦!

Test1執行的結果為100毫秒(大概的平均值)。

Test2執行的結果卻要12000毫秒。

Test3執行的結果更是增加到36000毫秒。

所以......愛護你/妳的程式、增加你/妳程式的效能,請從減少不必要的參數開始。

但萬一真的有必要,要使用「很多判斷式」.......把Test1/Test2/Test3改造成下列型式,然後參數規格都修改成一樣........


結果執行速度就差異不大...頂多1~2%,而且浮動性很高,極可能是「記憶體回收」或是其他干擾造成的。

重點在於:宣告階段影響程式效能的關鍵在「參數多寡」。



對!我聽到馬上有人質疑:反正一個物件宣告完後就擺在哪,何必計較宣告動作的效能呢?

今天假設是要做遊戲,比如某個關卡會有無限的「飛彈」、「小怪物」產生,「飛彈」不停被擊落、又不停射出,「小怪物」不停被打死、又不停被召喚........

當然可以把飛彈/怪物本身「被擊落與否」、「死亡與否」用純粹參數代替,(飛彈被擊落?重回原點等待發射,怪物死亡?重回原點等待召喚。)

如果採用這個做法,那確實沒有考量這點差異的必要。



但思考一下這個效能差異的由來......

雖然上面的附圖沒有截載,但關鍵在於記憶體。

記憶體配置?記憶體寫入?.......不管是哪一點,如果換個迴圈跑法,只是單純的做個ArrayList,然後一直塞物件進去、看記憶體何時爆掉........

Test3最快,Test2大約要Test3的三倍,Test1則是Test2的兩倍多一些......

還沒有機會測試使用了介面後的結果,但想必是相同的,因為使用介面根本不會有太多影響,介面(似乎)是類別的一部份,只會存在類別中,而不在物件存於記憶體的「標記/區段」上。

2014年2月11日 星期二

【JAVA】if...else if...else...判斷式,怎樣寫效能才會好?(3) 拿switch做比較

承續上一篇......我的「無聊神經」一旦開始運轉好像停不下來。

但是這次改用switch做比較。


我把這個迴圈用個函數包起來,a就是函數的傳入引數。

另外有一個函數在同樣的迴圈中寫入了「if...else...」,如下圖:




這兩個迴圈/函數執行的方式是......

run為switch,run1則是「if...else...」。為何要這樣做?run(1)和run(2)執行的結果不列入比較,原因看上一篇。剩下的.....做實驗當然要有充分的數據。

以下是結果...a是run函數輸出的,b則是run1......


先聲明:要使用switch或if來進行條件判斷,效能並不是優先考量......很多時候根本沒得選,因為switch只能判斷數值。(這算是「判斷」嗎?感覺跟分類沒兩樣。)

所以雖然效能明顯快了兩成,但其實只是作為一種比較而已。

2014年2月10日 星期一

【JAVA】if...else if...else...判斷式,怎樣寫效能才會好?(2)

上一篇,寫完後發現應該有個更客觀、更有準確的方法可以來測試,所以我先重新設計了作為基準/比對的「if...else...」,如下圖:




但跟上一篇不同的地方是我將它做成了一個函數...並且用以下的方法執行:


並且得到結果:

注意到了嗎...第1/2次的測試結果跟接下來的3/4/5/6差異過大。不管程式重複執行再多次也一樣。(這挺可怕的...雖然差異只是1~2%左右。)

不過這是插曲,接下來是我修改run()這個函數的內容的方法......


先聲明,用註解、或測底刪除程式,結果沒有明顯差異。測試結果如下圖.......




「if...else...」確實會明顯造成執行效能的差異。

這個測試法還有得搞.........(下一篇)

2014年2月7日 星期五

【JAVA】if...else if...else...判斷式,怎樣寫效能才會好?

「if」怎麼使用?

寫這個未免也太娘太小家子氣太學生口味了!(沒有瞧不起人的意思,感謝網路上無數的教學網站和教學文,但...你們還有需要加強的地方。)

參考一下我以前測試「效能」的方法,現在用來測下面這兩種「if」寫法在執行上會有多少效能差異......

IF1


IF2

上圖稱為IF1,下圖稱為IF2。因為我用個三層式的for迴圈來進行測試,所以會有i/j/k三個數值出現。

c1/c2的型態為long。看看他們被遞增的if條件式......是完全一樣的!也就是說如果c1被遞增、c2也會被遞增。唯一的差異就在於if...else的執行順序而已。

就理論上來說,「if」會被逐一執行,也就是說如果第一行if的條件吻合,則剩下的if都不會被執行,即使有條件更嚴謹、更精確、更穩和的。也就是說,理論上IF1執行起來會比較慢。

但另一個真正的問題是......要做if判斷,會需要耗掉多少資源。(沒辦法精準測量,只能取個概念。)

測試結果的彈性變化差異很大。



i/j/k的遞增極限都是1200,──k遞增到1200時會歸零,然後把j遞增1,j遞增到1200時也會歸零,然後把i遞增1......直到i也是1200,這個迴圈宣告結束。

limit1的值越小,IF1被執行到最後一行的機率就越高,理論上來說消耗的資源也越高。

當我把limit1定在400時,IF1執行完花了1769millisecond,IF2只花了836。

但當我把limit1定在800時,IF1執行完花了372millisecond,IF2只花了252。

當我再把limit1定在1000時,IF1執行完花了101millisecond,IF2只花了79。

最後但當我把limit1定在1200時,IF1執行完花了27millisecond,IF2只花了16。



這結果挺詭異的...我沒預想到,其實應該只要專注在小於800的數字就好。我擔心IF的條件太少會失去意義,但顯然我的IF條件太多...但又不夠多!(所以當limit1設在1200時,兩者的執行效率沒辦法達到一樣,因為我沒有精確的把所有i/j/k的狀況列入。)

可是結果肯定有差.......

如果寫了一長串的「if...else...」判斷式,然後又把常用的都擺在最後頭,程式的效能差異可以到達兩倍之多。(還沒有嘗試增加判斷式的難度會有何差別,那雖然不難.....但細節很多。)



這不單單只是效能測試而已!

程式碼光是簡潔還不夠,判斷式光是正確還不夠.......因為我們沒辦法預料這自己寫的判斷式會碰到什麼樣的資料/數據。我們沒辦法精準的保證「自己最前頭的判斷條件一定會被優先執行」。



所以會有使用函數並搭配return來控制函數執行的需要。不過這是改天再寫的了。

(但如果是我,我會用物件的多型性來取代這一長串判斷式。這有機會再寫的了。



點這是看續篇.......(我怎麼這麼無聊,連這種東西都寫續篇。)