2017-08-24 69 views
0

我在Javascript性能問題,在工作最近導致飛機墜毀。隨着現代化的目標我們的應用程序,我們正在進入運行我們的應用程序作爲Web服務器,在其上我們的客戶將通過一個瀏覽器(Chrome,火狐,...)連接,並有我們所有正在運行的HTML + JS網頁接口。績效的WebSockets BLOB解碼造成內存問題

爲了給你我們的性能要求的概述,我們從攝像機源的應用程序運行的圖像處理,超過20個FPS在某些情況下運行,但在大多數情況下,各地2-3fps最大。

基本上,我們有C++編寫,其HTTP請求Web服務器,並且向用戶提供該接口的HTML頁面和該應用程序的相應的JS腳本。 爲了簡化兩個應用程序之間的通信,我然後在網頁和C++服務器之間打開一個Web套接字來發送格式化消息。這些消息可能相當大,可達幾個Mos。

這一切都工作得很好,只要保持FPS相對較低。當fps增加時,會發生以下兩件事。

  1. 當沒有更多內存可用時,C++ web服務器內存佔用增加非常快並且崩潰。經過調查,發生這種情況時,網絡使用充分,websocket緩存填滿。我認爲這是由於websocket採用TCP-IP的方式,因爲套接字必須等待發送和接收消息才能發送下一個消息。
  2. 或者瀏覽器崩潰了一段時間後,顯示喔唷,崩潰屏幕(見下圖)。看起來在這種情況下,同樣的事情或多或少發生,但似乎這次是由於垃圾收集策略。下圖顯示了應用程序運行時內存使用情況的打印屏幕,清楚地顯示了鋸齒圖案。這似乎表明,垃圾收集正在進行的工作間隔越來越遠。

Aw Snap screen

Saw memory pattern

我已經困問題降低到非常大的消息(> 100K上)以每秒快的速度發送。信息越大,發生得越快。爲了使用我收到的消息,我啓動了web worker,將我收到的blob傳遞給web worker,webworker使用FileReaderSync將消息轉換爲ArrayBuffer,並將其傳遞迴主線程。我期望這篇文章有相當多的副本,但我對JS還不太熟悉,所以要確保這個說法。另外,我initialy做同樣的事情,而不webworker(的FileReader),但幀率和CPU使用率是非常糟糕......

下面是代碼我打電話到信息解碼:

function OnDataMessage(msg) 
{ 
    var webworkerDataMessage = new Worker('/js/EDXLib/MessageDecoderEvent.js'); // please no comments about this, it's actually a bit nicer on the CPU than reusing the same worker :-) 
    webworkerDataMessage.onmessage = MessageFileReaderOnLoadComManagerCBack; 
    webworkerDataMessage.onerror=ErrorHandler; 
    webworkerDataMessage.postMessage(msg.data); 
} 

function MessageFileReaderOnLoadComManagerCBack(e) 
{ 
    comManager.OnDataMessageReceived(e.data); 
} 

和在webworker代碼:

function DecodeMessage(msg) 
{ 
    var retMsg = new FileReaderSync().readAsArrayBuffer(msg); 
    postMessage(retMsg); 
} 

function receiveDecodingRequest(e) 
{ 
    DecodeMessage(e.data); 
} 

addEventListener("message", receiveDecodingRequest, true); 

我的問題有以下幾點:

  1. 是否有通過例如告訴我用來重複使用緩衝區而不是重新創建緩衝區的一些部分,或者保持GC工作區間固定,從而使GC不必重複收集太多內存。這是我知道如何使用C++,但在JS?

  2. 是否有另一種方法我應該用於我的大有效載荷?請記住,傳輸應儘可能快。

  3. 是否有讀取BLOB數據arraybuffers另一種方法,將比我做什麼更快?

我提前感謝您的幫助/意見。

回答

0

事實證明,內存問題是由於新WebWorker線,並在WebWorker新FileReaderSync線。

刪除這些大大提高了性能!

另外,事實證明,這個解碼操作是不必要的,如果我想使用的WebSocket作爲數組緩衝區。我只需要將websockets的binaryType屬性設置爲「arraybuffer」...

因此,總而言之,一個非常簡單的解決方案,在***問題的痛苦:-)