Wednesday, April 09, 2008 - 文章

沒浴火卻重生的小黑電池

還記得我是怎麼寶貝我的T43電池嗎?

不過,我沒說出來的是,這個故事並沒有幸福的結局。

儘管用了近乎變態的手法呵護電池(好像買了名牌雨傘,寧可淋雨也捨不得拿出來撐),不到一年的時間,電池就開始會從60%瞬間掉到4%。經驗中,這是電池老化的正常現象,但我的X21電池狂操猛用了四年多才發生,這顆充不到70次、用不到三年、平日呵護有加的電池居然如此不成器,真叫人情何以堪~~~

就在上個月月底,連續幾次發現機器切到Standby後,再開機變成"前一次未正常關機"。仔細檢查,發現電池容量會一直停在49%,無法充電,一拔整流器就斷電。這電池已經死絕了! 連當UPS都不夠格。

雖然電池的法定保固只有一年,但機器還在三年保固內,加上電池內部記憶資訊可以證明它只充了不到70次就掛點,這些都算是很有力的"相罵本"。正打算抄起電話打去客服專線罵人,小熊子傳來一篇來自天堂的網頁,聯想自願召回一批2006/07年出貨的小黑電池。利用它附的程式檢查電池序號,嘿! 我的電池是召回之列! 深入追查,才驚覺這批黑心電池曾經在洛杉磯表演過火燒T43的大絕招。想起我常將機器切成Standby就收起來... 頓時有死裡逃生的感覺。只是我不確定黑心電池的瑕疵除了可能會不定期施展火鳥功之外,包不包含異常的性能衰退?

無論如何,有驚無險地撐了兩年多,這下可以換到一顆新電池重頭開始囉! 電話問過客服,他們表示無法直接在客服中心更換,必須按照程式的提示填寫申請表直接上傳(只准填英文,莫非要直接從國外寄給我?),再將申請表編號Mail給他們以便"跟催"。寄去編號沒多久,我又收到一封信說上回填的資料因"資料庫問題"變成亂碼無法閱讀,請我另外填寫中文姓名、地址。
(我懷疑這是一個"人工"整合的作業流程,之前上網寫的資料都是填心酸的,第二次要了中文地址,接由台灣物流機制遞送才是真實的流程,也才符合時效及成本。)

兩週後的今天,新電池寄到了(快遞人員會一併回收舊電池)。就這樣,兩年多的阿公級小黑配上全新的電池,由充電次數零重新出發囉! 特此紀念。

KB-Javascript Anonymous Function Memory Issue

過去撰寫Javascript事件,我傳統的寫法會宣告一個事件函數,再把它掛到對應的元素上,例如:(以ASP.NET AJAX Client Library為例)

<input type="button" id="btn" value="Click!" />
<script type="text/javascript">
$addHandler($get("btn"), "click", btnClick);
function btnClick(evt) 
{
    alert(evt.target.value);
}
</script>

自從開始使用jQuery,範例看多了,我也開始習慣用Anonymous Function的方式宣告事件函數,例如:

$("#btn").click(function() {
    alert(this.value);
});

這種寫法可以省去想函數名稱的困擾(老是花時間去想btnClick之類沒營養的名字,常覺得在浪費生命),更大的好處是事件函數本體就接在設定事件程式碼的下方,閱讀時不必上下Scroll尋覓(Visual Studio 2008雖有Javascript Intellisense, 畢竟無法像C#/VB.NET一樣用Goto Definition直接跳到函數所在),甚為方便。但我一直有個疑問: 如果$("#tbl td").click(function() {....});一口氣為數百個td加上Click事件,會不會同樣的函數程式碼就複製了上百份? 白白耗用了不必要的記憶體。

疑問在心中壓了很久,總算動手寫了一小段Code來驗證。

程式裡分別用匿名函數及具名函數的方式為一個div重覆掛上click事件3萬次,藉此觀察記憶體的使用狀況。

<html><head>
<title>Memory Usage Test</title>
<style type="text/css">
.clsDiv 
{ cursor: pointer; width: 300px; background-color: blue; color: white; }
</style>
<script type="text/javascript" src="lib/jquery.js"></script>
</head><body>
<script type="text/javascript">
$(function() {
    var count = 30000;
    $("#dv1").click(function() {
        for (var i=0; i < count; i++) 
        {
            $("#dv3").click(function() {
                var s = 
                    "01234567890123456789...用大量文字填充...01234567890123456789" +
                    //重覆多次
                    "01234567890123456789...用大量文字填充...01234567890123456789" +
            });
        }
        $("#dv3").html("dv1 Clicked!");
    });
    
    $("#dv2").click(function() {
        for (var i=0; i < count; i++)
            $("#dv3").click(fatFunc);
        $("#dv3").html("dv2 Clicked!");
    });
});
function fatFunc() {
    var s = 
    "01234567890123456789...用大量文字填充...01234567890123456789" +
    //重覆多次
    "01234567890123456789...用大量文字填充...01234567890123456789" +
}
</script>
<br /><div id="dv1" class="clsDiv">Anonymous Function</div>
<br /><div id="dv2" class="clsDiv">Named Function</div>
<br /><div id="dv3" class="clsDiv">Sheep</div>
</body>

以Task Manager觀察iexplorer.exe佔用記憶體大小當作指標,實驗結果:

測試名稱 執行前記憶體用量(KB) 執行後記憶體用量(KB)
Anonymous Function 54,024 83,144
Named Function 54,040 59,404

【結論】反覆宣告Anonymous Function的確會耗用較多的記憶體,但衡量其方便性及可閱讀性,仍可視需要使用。唯需注意較極端的例子(Client Memory極度匱乏、函數本身很擁腫、重覆宣告次數過高...),應調整成具名函數的寫法,以避免記憶體耗用過度影響效能。

搜尋

Go

<April 2008>
SunMonTueWedThuFriSat
303112345
6789101112
13141516171819
20212223242526
27282930123
45678910
 
RSS
【工商服務】
最新回應

Tags 分類檢視
關於作者

一個醉心技術又酷愛分享的Coding魔人,十年的IT職場生涯,寫過系統、管過專案, 也帶過團隊,最後還是無怨無悔地選擇了技術鑽研這條路,近年來則以做一個"有為的中年人"自許。

文章典藏
其他功能

這個部落格


BlogLook Score and Rank

Syndication