星期五, 3月 25, 2011

Firefox 4.0 初步使用心得

做了一些 benchmark。我的機器:

  • Intel Core-i7 720QM:performance cpufreq governor
  • Transcend JM1333KSN-4G x 2:在測試時還剩下約 1GB 空間(扣掉 Buffer 則剩 3.5GB)
  • Linux 2.6.38:有開 per-session auto-group(CONFIG_SCHED_AUTOGROUP=y)

參賽的瀏覽器有:

  • Chromium 11.0.696.16:
    Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/534.24 (KHTML, like Gecko) Chrome/11.0.696.16 Safari/534.24
  • Firefox 4.0:
    Mozilla/5.0 (X11; Linux x86_64; rv:2.0) Gecko/20110323 Firefox/4.0
  • Opera 11.10 beta:
    Opera/9.80 (X11; Linux x86_64; U; zh-tw) Presto/2.8.119 Version/11.10

測試 0:

  • Acid3
    • Chromium:100/100
    • Firefox:97/100
    • Opera:100/100
  • 冷啟動速度:
    • Chromium:4.16s(8.33 次)
    • Firefox:1.5s(3 次)
    • Opera:5.16s(10.33 次)

冷啟動速度是執行「sync ; echo 3 > /proc/sys/vm/drop_caches」以後啟動瀏覽器到視窗出現,游標閃爍的次數(每次 0.5s)。測了三次,精度不是很準確... 看看就好!

測試 1 - CPU 0%(幾乎沒有其他負載):

測試 2 - CPU 100%(make kernel, -j16):

其中「大頁面測試」一項,是先重整三次(確認檔案讀進了 filesystem buffer),然後再重整三次的成績平均。Chromium 快的很神奇 @@

為什麼會有在 CPU 100% 下的測試呢?因為我使用 Gentoo Linux,常常會編譯東西。可是在編譯的同時,也會一邊上網、看信... 等等。所以在 CPU 負載高的情況下使用瀏覽器是很常有的事情。

跑 Sunspider 的時候,Chromium 會更新每個跑完的測試結果,可是 Firefox 完全不會顯示東西(這算是偷吃步嗎?),Opera 會顯示,但是中間的藍色方框內會閃爍。

對我來說,瀏覽器的速度(網頁顯示速度、分頁切換速度、UI 反應速度)很重要。我無法忍受切換分頁或點個書籤要等一兩秒才看得到東西... 所以「使用心得」主要是速度測試。


附錄 - 大頁面測試使用的網頁:

<html>
  <head>
    <title>A very big page!</title>
    <script language="javascript">
      var startTime = new Date();

      function showElapsedTime() {
        var endTime = new Date();
        var elapsedTime = Number(endTime - startTime);

        document.getElementById("results").innerHTML =
          "took " + Number(elapsedTime / 1000) + " sec";
      }
    </script>
  </head>
  <body onload="showElapsedTime();">
    <p id="results">calculating...</p>
    <p>這裡是很長很長的段落</p>
    <p>重複 n 次</p>
    <p>導致這個檔案長大到 10MB...</p>
  </body>
</html>

星期三, 3月 23, 2011

C/C++: i = i++ + ++i;

這樣的一段 code,結果應該是什麼呢?

答案是「不一定」!

在 C/C++ 之中,operator + 並不是 sequence point。例如,運算式「f() + g()」之中,是 f() 先執行還是 g() 先執行,順序是不一定的(跟編譯器實做有關)。所以「i++ + ++i」之中,有可能 i++ 先作,亦有可能 ++i 先作。

並且,如「i=i++;」這樣的式子之中,i 被指派兩次。「i=」的指派動作可能發生在「i++」的指派動作之前、之後、或之間。

所以,為了節省 debug 耗用的腦細胞,任何程式設計師都不應該寫出這樣的程式碼。

====== 囧rz [分隔線] 囧rz ======

額外一提,「std::cout << f() << g();」這樣的程式碼之中,f() 與 g() 的執行順序也是不一定的。這是由於 C++ 的 operator overload 視為 function call。而 C++ 的 member function 實際上會被轉換成多傳入一個 this 引數的 global function。

例如(以下程式並非合法的 C++ code,只是為了解釋程式的行為):

std::cout << f() << g(); // 1
可能被轉成
std::cout.operator << (f()).operator << (g()); // 2
再被轉成
std::ostream::operator << (std::ostream::operator<< (std::cout, f()), g()); // 3

在上述 3 之中,是「std::ostream::operator<< (std::cout, f())」先執行還是「g()」先執行,順序也是不一定的。

所以,若 f() 與 g() 裡面都有輸出,則有可能先看到 g() 的輸出才看到 f() 的輸出,或是剛好相反。例如:

// 可能性 1:
tmp1 = f(); // 列印 f() 裡面的輸出
std::cout << tmp1; // 列印 f() 的結果
tmp2 = g(); // 列印 g() 裡面的輸出
std::cout << tmp2; // 列印 g() 的結果
// 可能性 2:
tmp1 = g(); // 列印 g() 裡面的輸出
tmp2 = f(); // 列印 f() 裡面的輸出
std::cout << tmp2; // 列印 f() 的結果
std::cout << tmp1; // 列印 g() 的結果

延伸閱讀:http://en.wikipedia.org/wiki/Sequence_point