上篇文章剖析了SignalR的四種傳輸方式: Forever Frame、Long Polling、Server Sent Event及WebSocket,延伸出另一個議題,這四種傳輸方式效率如何? 理論上WebSocket Overhead最少且支援雙向傳送,很有HTML5傳輸霸主之相,但我期待眼見為憑。
我設計了以下的實驗,先測Server端傳至Client端的效率,沿用前文的MarathronHub,以亂數模擬1000筆Runner資料,經由BatchTest()方法一骨腦把1000筆資料拋至Client端: (註: 程式碼改寫自傳輸剖析一文,這裡只提增修的部分,請對照參考)
publicvoid 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>加至網頁下方列表,方便連續測試記錄之用。
<!DOCTYPEhtml>
<htmlxmlns="http://www.w3.org/1999/xhtml">
<head>
<title></title>
<scriptsrc="../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 [ <spanid="spnTransType"></span> ]</h3>
<div>
<inputtype="button"value="Test"/>
Runner Count = <spanid="spnCount"></span>
</div>
<fieldset>
<ulid="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的威力。