2014-07-18 14 views
7

myślę używam do wycieku pamięci z ekspresowe aplikacji przy podłączeniu x liczba EventSource klientów do niego. Po połączeniu klientów i wysłaniu im x wiadomości i ich rozłączeniu, moja aplikacja zwolni tylko niewielką ilość przydzielonego Heap/RSS.Przeciek pamięci w Express.js z EventSource

Aby to potwierdzić, zapisałem Heapdump podczas uruchamiania serwera i jeden po podłączeniu 7000 klientów do niego i wysyłania x wiadomości do każdego klienta. Czekałem chwilę, aby dać GC szansę na oczyszczenie się przed zrobieniem zdjęcia sterty.

Aby porównać migawki sterty, wczytałem je w widoku profilu narzędzi programistów Chrome i wybrałem tryb "Porównanie".

Moje pytania są następujące:

1) Jak interpretować te liczby? (Dla porównania patrz załączony sterty snapshot zrzut ekranu.)

2) Na przykład wygląda na to, że gniazdo obiektów nie prawie za darmo wszelkie obiekty w ogóle, czy to prawda?

3) Czy mogę podać mi więcej wskazówek, aby zbadać problem?

Heap Snapshot Express.js app

+0

Jeśli ktoś jest zainteresowany w kodzie używam go przetestować, to jest tutaj: [Server & Client Code] (https: //gist.github .com/roundrobin/a6e3d38cb24fcc112418) – BausTheBig

+0

nie jest to przeciek pamięci, do którego dodano odniesienie i którego nie usunięto, ale nie zwolni pamięci, dopóki nadal będzie można uzyskać do niej dostęp. 'ALL_CLIENTS' ma rzeczy dodane do niego teraz zamykasz je tam, nie są usuwane z' ALL_CLIENTS', więc nadal istnieje odniesienie do nich po zakończeniu połączenia i połączenia 'delete ALL_CLIENT [key]' gdzie klucz jest Klucz bieżącego klienta, jeśli masz referencję, nie możesz usunąć danych tam, w przeciwnym razie możesz mieć odniesienie do innej pamięci aplikacji, jeśli wskoczysz tam –

Odpowiedz

1

Możesz być wolny od wycieków pamięci i jako bonus uniknąć śmieciarza. Wszystko co musisz zrobić, to odpytywanie obiektów.

Można zrobić coś takiego

var clientsPool = new Array(1000); 
var clientsConnected = []; 

Gdy nowy klient łączy, robisz

var newClient = clientsPool.pop(); 
//set your props here 
clientsConnected.push(newClient); 

to niesamowity sposób na uniknięcie śmieciarza i uniemożliwić wyciek pamięci. Oczywiście, jest trochę więcej pracy i będziesz musiał to ostrożnie zarządzać, ale jest to warte swojej wydajności.

Jest niesamowita rozmowa o tym, tutaj idziesz https://www.youtube.com/watch?v=RWmzxyMf2cE

+0

nie paruj inni członkowie odpowiedzieć !!! –

+0

para jak "ukraść"? Jeśli spojrzysz bardzo uważnie, nasze odpowiedzi są różne. Wykonuje iteracje przez wszystkich klientów, podczas gdy ja nie zgadzam się z pollingiem. Używa też słowa kluczowego delete, które jest bardzo złe. Podsumowując ... przysięgam, że nie skopiowałem! Napisałem to z mojego umysłu, nie jestem złodziejem = (( – Magus

+0

co się stanie, jeśli nie chcesz, aby Twój pomysł był świetny, jeśli wiesz dokładnie, ilu ludzi ma się połączyć lub z przyjemnością ogranicza połączenia z serwerem, ale co jeśli nie chcesz tego ograniczać? ​​powiedzmy, że apache zrobił to i odszedł najwięcej połączeń, to 1000 stron internetowych byłoby naruszone, że 1 strona może wymagać 10 lub tak połączeń, co oznaczałoby, że tylko 100 użytkowników mogło połączyć się z tym serwerem apache, są lepsze sposobów niż przy użyciu delete tak, ale przy użyciu limitu nie jest sposób to zrobić ... –

1

Jak na mój komentarz ...

Javascript nie można wyjaśnić sekcję pamięci powinno coś być skierowany na nią około 2 lat temu ktoś znalazł exploit i szybko został zamknięty tak i to działa tak

var someData = ["THIS IS SOME DATA SAY IT WAS THE SIZE OF A SMALL APPLICATION"]; 
var somePointer = someData[0]; 
delete someData; 

potem wstrzykuje aplikację do somePointer jak to było odniesienie do miejsca w pamięci, kiedy nie było żadnych danych teraz. hej, presto, wstrzyknęłaś pamięć.

Więc jeśli jest mowa jak wyżej somePointer = someData[0]; nie można zwolnić pamięć aż delete someData więc trzeba usunąć wszelkie odniesienia do cokolwiek chcesz czyszczących w przypadku ALL_CLIENTS.push(this); na linii 64 jest dokonanie Państwa pamięci systemowej dostępne za pośrednictwem ALL_CLIENTS, więc co można zrobić, to

Linia 157

_.each(ALL_CLIENTS, function(client, i) { 
        var u; // holds a undefined value (null, empty, nothing) 
        client.close(); 
        //delete ALL_CLIENTS[i]; 
        ALL_CLIENTS[i] = u; 
        ALL_CLIENTS.unused++; 
       }); 

Na innym uwaga to nie jest pamięć wycieku przeciek pamięci jest powiedzieć, że ten serwer go zamknąć, jeśli pamięć nie zwolnić po jej wyjściu wtedy masz przeciek pamięci, jeśli tak oczyść pamięć za sobą, to nie jest przeciek, to po prostu kiepskie zarządzanie pamięcią.

Dzięki @Magusowi za wskazanie, że usunięcie nie jest najlepszą rzeczą, jakiej możesz użyć, ale nigdy nie poleciłbym implementacji ograniczającej struktury, ale możesz spróbuj

Linia 27: ALL_CLIENTS.unused = 0;

Linia 64:

var u; 
if(ALL_CLIENTS.unused > 0){ 
    for(var i = 0; i < ALL_CLIENTS.length; i++){ 
     if(ALL_CLIENTS[i] == u){ 
      ALL_CLIENTS[i] = this; 
      ALL_CLIENTS.unused--; 
      i = ALL_CLIENTS.length; 
     } 
    } 
}else{ 
    ALL_CLIENTS.push(this); 
} 
+0

W tej notatce to tylko pierwsza rzecz, którą znalazłem w ten sposób, sprawdź swój kod po więcej odniesień, których nie kasujesz, gdy chcesz zwolnić pamięć –

+0

Dzięki, pozwól mi to sprawdzić i akceptuję twoją odpowiedź! – BausTheBig

+0

Proszę, nigdy nie używaj słowa kluczowego Usuń! Zadaje więcej szkód niż pożytku. Nie ma problemu z utrzymaniem obiektu w pamięci, jeśli później go użyjesz ponownie. Przechowuj wszystko w pamięci i korzystaj z tych samych obiektów dla różnych klientów, dzięki temu unikniesz czasu alokacji, czasu deallokacji (usuniesz słowo kluczowe zrujnuje twoją wydajność) i czasu zbierania śmieci.Obejrzyj film, który zamieściłem w mojej odpowiedzi, aby uzyskać więcej informacji, warto to zrobić. – Magus

Powiązane problemy