11

Mam aplikację, która odbiera wiadomości binarne przez WebSocket często (przynajmniej raz na klatkę) i rysuje dane, używając canvas/webgl. Zauważyłem, że mam całkiem niezły profil pamięci piłokształtnej; wiele krótkich fragmentów danych. enter image description hereCzęsto zadawane przez WebSocket zera-kopia

To mnie nie dziwi, ponieważ jestem otrzymaniu przedmiotu z onmessage, co najmniej raz na 16ms, który jest używany do rysowania, a następnie de-odwołuje.

Moje pytanie brzmi: czy są jakieś wskazówki, jak tego uniknąć/zminimalizować? Opierając się na WebSocket API, nie wydaje się być alternatywą dla posiadania nowej pamięci przydzielonej na każde połączenie odbierania gniazda. W innym języku/środowisku, wstępnie przydzielę trochę pamięci i odbiorę do tego bufora, aby uniknąć stałego przydzielania pamięci dla obiektów krótkotrwałych, ale nie mogę wymyślić żadnego oczywistego sposobu osiągnięcia tego w JavaScript w przeglądarce.

Dla odniesienia, oto mój widok Frames.

enter image description here

Nie wiem, czy to czas bezczynności jest zbieranie śmieci? Wszelkie dociekania ninja z narzędziami od narzędzi będą bardzo mile widziane.

+0

Masz jakieś próbki kodu? zacząłem coś? skrzypce? – Anonymous0day

+1

Mam ten sam problem z datą czujnika transmisji strumieniowej z mojego raspberry pi przez WebSockets. Obawiam się, że nie ma i nie będzie możliwości ingerencji w pamięć alokacji WebSockets w javascript. Moje badania nie przyniosły żadnych rezultatów. – windm

+0

Co masz nadzieję osiągnąć? Jak długo działa program i jak ważna jest spójna, długowieczna wydajność? Zobaczenie małego kodu lub próbki kodu byłoby wspaniałe –

Odpowiedz

1

Nie wiem czy zrozumiałem swój problem, ale można zadeklarować globalną tablicę jak w każdym innym języku i używać go jako bufora okrężnego, na przykład:

var buffer = []; 
var bufferLength = 1000; 
var start = 0; 
var end = 0; 
var content = 0; 

socket.onmessage(function(msg) { //msg allocated 
    end %= bufferLength; 
    if (end == start && content != 0) 
     console.log("Buffer is full"); 
    else { 
     content++; 
     buffer[end++] = msg; //reference to msg saved so it's not destroyed at the end of the callback 
    } 
}); 

function getNext() { 
    start %= bufferLength; 
    if (start == end && content == 0) 
     console.log("Buffer is empty"); 
    else { 
     content--; 
     return buffer[start++]; // returns reference to next msg 
    } 
} 

Edit: I zmodyfikowane odpowiedź jest bardziej wyczyść o cyklu pamięci:

JS przydzieli pamięć dla odebranej wiadomości na stronach internetowych i utworzy odniesienie do niego o nazwie msg, które zostanie ci przekazane jako parametr w wywołaniu zwrotnym zdefiniowanym dla onmessage.

Uwaga JS GC zniszczy tylko ten fragment pamięci, gdy nie jest już przywoływany w kodzie.

To, co robię powyżej, zapisuje to odwołanie wewnątrz bufora, więc wartość nie zostanie zniszczona po wykonaniu wywołania zwrotnego i można uzyskać do niego dostęp później za pomocą getNext. Nie musisz przydzielać nowej pamięci, ponieważ JS zrobił to za Ciebie.

Jeśli chcesz sklonować lub utworzyć inną kopię msg, istnieje kilka różnych opcji. Prostym rozwiązaniem, które pozwoli Ci sklonować nieokrągłe obiekt JSON będzie:

var newJSON = JSON.parse(JSON.stringify(msg)); 

można znaleźć więcej informacji o alokacji pamięci w JS w https://developer.mozilla.org/en-US/docs/Web/JavaScript/Memory_Management

+0

To nie odpowiada na moje pytanie, które dotyczy konkretnie "nowa pamięć przydzielona na każde gniazdo odbiera połączenie". – sethro

+0

Dotyczy konkretnie pamięci przydzielonej dla obiektu przekazanego do 'onmessage':' msg'. Myślę, że nie rozumiesz mojego pytania. Pytam o sposób wstępnego przydzielenia bufora, z którego WebSocket lub być może jakiś inny interfejs API będzie pobierał dane z podstawowego gniazda. – sethro

+1

Ok, rozumiem teraz twój problem. Nie sądzę, żebyś mógł coś z tym zrobić za pomocą JS. Być może uda ci się złagodzić niektóre z całkowitego opóźnienia umożliwiającego rasteryzer zerową w chrome chrome: // flags/# enable-zero-copy, dzięki czemu renderowanie będzie szybsze w webgl. Ponadto, biorąc pod uwagę twój problem związany z dostępem do pamięci, możesz grać z liczbą/rozmiarem pakietów wysłanych z serwera, mniej/większe pakiety zmniejszą liczbę operacji. –