上篇文章剖析了SignalR的四種傳輸方式: Forever Frame、Long Polling、Server Sent Event及WebSocket,延伸出另一個議題,這四種傳輸方式效率如何? 理論上WebSocket Overhead最少且支援雙向傳送,很有HTML5傳輸霸主之相,但我期待眼見為憑。

我設計了以下的實驗,先測Server端傳至Client端的效率,沿用前文的MarathronHub,以亂數模擬1000筆Runner資料,經由BatchTest()方法一骨腦把1000筆資料拋至Client端: (註: 程式碼改寫自傳輸剖析一文,這裡只提增修的部分,請對照參考)

        public void BatchTest()
        {
            var caller = Clients.Caller;
            foreach (var runner in dataStore.Values)
            {
                caller.addRunner(runner);
            }
        }

聲明在先,實務上我們很少會產生如此兇猛的資料傳輸量,理由有二: 1) 送至前端的資料多半會反應在UI上,短時間產生巨量資料,遠超過使用者視覺所能接收消化的上限,意義不大。 2) 若使用者從Internet連上網站,網路頻寬有其限制,若是透過行動裝置瀏覽,更要考量CPU/Memory負載,能達成巨量資料傳輸的可行性存疑。進一步,設計實務上更建議對即時傳輸加上節流控制,限定單位時間可傳送資料量上限,以維持良好的效能及效果。雖然高速傳送大量資料的情境很少真實上演,這類測試結果還是可視為"壓力測試",具有一定參考價值。

前端程式如下。由?trans=…參數指定傳輸方式,按下測試鈕會觸發Server端BatchTest(),傳回1000筆Runner資料。addRunner()除將資料放入陣列,還一併顯示耗時,遇到最後一筆(runner.Name == "Last"),便將結果產生一筆<li>加至網頁下方列表,方便連續測試記錄之用。

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <title></title>
    <script src="../Scripts/jquery-1.10.2.js"></script>
    <script src="../Scripts/jquery.signalR-2.0.0.js"></script>
    <script src="../signalr/hubs"></script>
    <script>
        $(function () {
            var marathron = $.connection.marathron;
            runners = [];
            var $counter = $("#spnCount"), startTime;
            marathron.client.addRunner = function (runner) {
                runners.push(runner);
                $counter.text(runners.length + "@" + (new Date() - startTime) + "ms");
                if (runner.Name == "Last")
                    $("#ulDisplay").append("<li>" + $counter.text() + "</li>");
            };
 
            var re = /[?]trans=(.+)/;
            var m = re.exec(location.href);
            var transType = m && m.length > 1 ? m[1] : null;
            $("#spnTransType").text(transType);
            // Start the connection
            $.connection.hub.start(transType ? { transport: transType } : undefined)
            .done(function () {
                $(":button").click(function () {
                    startTime = new Date();
                    runners = [];
                    marathron.server.batchTest();
                });
            });
        });
    </script>
    <style>
        fieldset { margin: 6px; }
    </style>
</head>
<body>
    <h3>Transport Type [ <span id="spnTransType"></span> ]</h3>
    <div>
        <input type="button" value="Test" />
        Runner Count = <span id="spnCount"></span>
    </div>
    <fieldset>
        <ul id="ulDisplay"></ul>
    </fieldset>
</body>
</html>

網頁執行效果如下圖:

實測結果如下: (資料定量,時間愈短愈快)

  • IE10 Forever Frame
    545ms, 490ms, 450ms, 517ms, 533ms
  • IE10 Long Polling
    664ms, 693ms, 628ms, 659ms, 618ms
  • IE10 WebSocket
    533ms, 469ms, 564ms, 565ms, 546ms
  • Chrome Long Polling
    343ms, 312ms, 249ms, 280ms, 312ms
  • Chorme Sever Sent Events
    234ms, 249ms, 250ms, 250ms, 218ms
  • Chrome WebSocket
    234ms, 234ms, 218ms, 234ms, 234ms

【結論】

以Server對Client的單向傳輸來說,不管是IE或Chrome,Long Polling都是最慢的,因為每次得到結果後需結束原有Request重發一個新的。排除了Long Polling,IE10的Forever Frame與WebSocket,Chrome的Server Sent Event與WebSocket速度差不多,看不出明顯差距。而你知道我知道獨眼龍都知道的事實是–Chrome比IE10快。

在單純Server傳送給Client的情境,WebSocket並未展現明顯優勢,下回我們再測試雙向傳輸,見識WebSocket的威力。


Comments

# by mis2000lab

驚!...Chrome比IE10快.... (捶胸頓足大哭)不可能啊!神功護體啊 神功護體啊 神功護體啊 P.S. 黃飛鴻-男兒當自強的電影台詞 :-)

Post a comment