2016-05-19 6 views
1

Ich lese viel über Puffer Lecksuche in Netty4 und für mich sieht es aus wie es gibt keine deterministische Möglichkeit, solche Lecks in Unit-Tests zu erkennen.Netty 4/5 Deterministische Puffer Lecksuche, die in Unit-Tests verwendet werden kann

Die Bedeutung einer solchen Funktion für Komponententests ist jedoch so groß, dass es sich sehr falsch anfühlt, dass es keine klaren Richtlinien dafür gibt.

Zudem haben die meisten der Quellen einschließlich der sehr Originaldokument http://netty.io/wiki/reference-counted-objects.html Dinge erstaunlich verwirrend machen, indem sie vage Hinweise wie:

„Die folgende Ausgabe zeigt ein Leck aus unserer Unit-Test (XmlFrameDecoderTest.testDecodeWithXml()) : "

Das klingt, als ob es eine Möglichkeit gibt, Lecks in Pufferzuweisern in Komponententests deterministisch zu erkennen, während dies in der Tat nicht der Fall ist, wie Trustin Lee selbst in seinen Antworten bemerkt (Link unten).

Kein Wunder, dass dies dutzende Male von verschiedenen Quellen, die keine Ahnung haben, repetiert wurde, und nur Wörter kopieren und einfügen, ohne zu testen.

*) Trustin Lee schlug vor, eine Anwendung für 30 Sekunden unter einer stark ausgelasteten Arbeitslast in dem folgenden Thema auszuführen. Netty 4/5 does not actually detect resource leak of bytebuf? Allerdings löst das für mich keine Erkennung oder Ausgabe von ResourceLeakDetector aus.

*) Ich habe auch versucht, den GC-Trick in dem folgenden Thema How to force garbage collection in Java? vorgeschlagen, aber das macht auch keinen Unterschied.

GC ist so unberechenbar, dass es sehr schwer vorstellbar ist, wie ResourceLeakDetector genutzt werden kann, um saubere und gründliche Pufferleck-Komponententests zu erstellen.

*) Eine andere Methode ist refCnt für jedes einzelne ByteBuf zu testen, das erstellt wurde, während ein Test ausgeführt wurde. Aber manchmal ist es unmöglich, jede solche Referenz zu erhalten, da eine Schnittstelle String als Eingabeparameter deklarieren könnte und ihre Implementierung intern eine ByteBuf-Instanz erstellen und freigeben würde, und diese Referenz für Unit-Tests nicht erreichbar ist Es kam nicht zu einem Leck, das in Komponententests nicht erkannt werden konnte.

*) Ich konnte auch keine einfache Möglichkeit finden, eine Liste aller vorhandenen Puffer aus dem Allokator zu bekommen, sonst wäre es möglich refCnt für jeden einzelnen zu überprüfen.


Ich frage mich, ob jemand kann teilen, was die besten Praktiken, die in deterministisch arbeiten und kann praktisch in Unit-Tests verwendet werden, um konsequent Puffer Lecks in großen Codebases zu finden, Netty Puffer Verteilern verwenden.

Bisher scheint es so, als ob Komponententests für diesen Zweck nutzlos sind, es sei denn, Sie betreiben einen vollwertigen Server für längere Zeit in Ihren Unit Tests (und das garantiert Ihnen übrigens auch nichts, erhöht nur Ihre Chancen in der Theorie). Soweit ich sehen kann, gibt es keinen guten Grund für solche Einschränkungen zu testen, aber wir haben was wir haben.

Es gibt so viele verwirrende Informationen zu diesem Thema im Internet, leider, die aus Netty-Dokumentation selbst stammen, dass ich wirklich will, dass die Fakten klar und deutlich formuliert werden.

Auch wenn die Antwort auf meine Frage lautet "es ist unmöglich", nur diesen Text verfügbar zu haben, könnte einige Leute viel Zeit beim Recherchieren einsparen.


P.S. Ein sehr einfaches Beispiel, um die fehlende Ausgabe zu demonstrieren. Wenn jemand sagen kann, welche Änderungen erforderlich sind, damit dieser Code die Leckausgabe erzeugt, wäre ich sehr dankbar.

http://gist.github.com/codekrolik/e55b8ece07270f40aad85f691696fe6a

+0

Eine andere Idee war, die Zahl der Zuweisungen und Freigaben zu zählen und stellen Sie sicher, es gibt keine baumelnden aktiven Puffer . Aus diesem Grund habe ich versucht, Informationen über Arenen zu nutzen, die von Allokatoren aus zugänglich sind. Die Inkonsistenz der zurückgegebenen Zahlen ist jedoch so überwältigend, dass sie mit Sicherheit nicht dazu verwendet werden können, einen stabilen, lecksicheren Komponententest zu erstellen. https://gist.github.com/codekrolik/6aa035ac650ea2972e532227a355a0e4 –

+0

Zum Beispiel, wenn ich 50000 Zuweisungen und Freigaben laufen, die von Arenen zurück Statistiken sind wie folgt aus: directActive 0 directAlloc 1 directDealloc 1 heapActive 0 HeapAlloc 0 heapDealloc 0 Aber wenn ich die Freigabe Zeile aus kommentieren, plötzlich wird der Ausgang directActive 50000 directAlloc 50000 directDealloc 0 heapActive 0 HeapAlloc 0 heapDealloc 0 –

Antwort

0

So habe ich Unit-Tests für mich arbeiten lassen.

Der Mechanismus ist wie folgt aus:

1) Erstellen Sie eine PooledBufferAllocator mit behinderten Cache, wie in https://github.com/netty/netty/issues/5275

PooledByteBufAllocator alloc = new PooledByteBufAllocator(true, 1, 1, 8192, 11, 0, 0, 0); 

2) vorgeschlagen wurde Sicherstellen, dass alle Bootstraps verwenden diese allocator

ein. Kunde

Bootstrap clientBootstrap = new Bootstrap(); 
clientBootstrap.option(ChannelOption.ALLOCATOR, alloc); 

b. Server

ServerBootstrap serverBootstrap = new ServerBootstrap(); 
serverBootstrap.option(ChannelOption.ALLOCATOR, alloc) 
    .childOption(ChannelOption.ALLOCATOR, alloc); 

3) Nach dem der Test durchgeführt wird, überprüfen Puffer Lecks für den direkten und Heap-Puffer

assertEquals(0, getActiveDirectBuffers(alloc)); 
assertEquals(0, getActiveHeapBuffers(alloc)); 

int getActiveDirectBuffers(PooledByteBufAllocator alloc) { 
    int directActive = 0, directAlloc = 0, directDealloc = 0; 
    for (PoolArenaMetric arena : alloc.directArenas()) { 
     directActive += arena.numActiveAllocations(); 
     directAlloc += arena.numAllocations(); 
     directDealloc += arena.numDeallocations(); 
    } 
    System.out.println("directActive " + directActive + " directAlloc " + directAlloc + " directDealloc " + directDealloc); 
    return directActive; 
} 

int getActiveHeapBuffers(PooledByteBufAllocator alloc) { 
    int heapActive = 0, heapAlloc = 0, heapDealloc = 0; 
    for (PoolArenaMetric arena : alloc.heapArenas()) { 
     heapActive += arena.numActiveAllocations(); 
     heapAlloc += arena.numAllocations(); 
     heapDealloc += arena.numDeallocations(); 
    } 
    System.out.println("heapActive " + heapActive + " heapAlloc " + heapAlloc + " heapDealloc " + heapDealloc); 
    return heapActive; 
} 
0

Für Unit-Tests, System.gc() hat für mich gearbeitet. (Ich bin mir nicht sicher, wie zuverlässig es ist, aber es scheint zuverlässig genug zu sein, um in den Tests genug GC zu erzeugen, um Lecks zu finden). Für mich waren die Lecks bei den Komponententests jedoch hauptsächlich darauf zurückzuführen, dass ich vergessen habe, den Puffer in den Tests freizugeben (nicht weil der Servercode selbst ein Leck hatte).

Wie Sie bereits erwähnt haben, könnte ein Integrations- und/oder Belastungstest dazu beitragen, Lecks im Server zu erkennen.

+0

Hier ist mein sehr einfaches Beispiel verwandelt, das nicht funktioniert. Würde es Ihnen etwas ausmachen, es zu ändern, damit es funktioniert? https://gist.github.com/codekrolik/e55b8ece07270f40aad85f691696fe6a –

Verwandte Themen