|
"I am creating a class with an Event, then I instantiate the class and dispose of it. VB seems to be wasting 16 bytes each time. "
I did some research, and found something really interisting. A small VB.Net application to test this showed that the memory usage slowly increases over time. The object never gets collected. A C# test worked as expected (memory usage increases the 1st time an object is created, and then it stays the same).
When I investigated the CLR code for this, I noticed why: C#'s ctor function only created the object, while VB's did the following:
IL_0001: call instance void [mscorlib]System.Object::.ctor() IL_0007: ldsfld class [mscorlib]System.Collections.ArrayList ConsoleApplication1.LeakingClass::__ENCList IL_000d: newobj instance void [mscorlib]System.WeakReference::.ctor(object) IL_0012: callvirt instance int32 [mscorlib]System.Collections.ArrayList::Add(object)
It seems to me as if it is adding the object to an arraylist (only if you have an event declaration in your class).
Is this a bug, or was it done for a reason (my best guess would be that it was done in order for other objects to still be able to respond to events raised by this object, even after it was disposed) And if it was done for a reason, is there a work-around (other than using C#)
I've included my testing code:
Imports System.Threading Module Module1 Private Const maxGarbage As Integer = 1000
Sub Main() Dim After As Long Dim Begin As Long GC.Collect() Begin = GC.GetTotalMemory(True) Console.WriteLine("Memory used at start: {0}", Begin) MakeSomeGarbage() Console.WriteLine("Memory used before collection: {0}", GC.GetTotalMemory(True)) While True GC.Collect() After = GC.GetTotalMemory(False) Console.WriteLine("Memory used after full collection: {0}", After) Console.WriteLine("Difference: {0}", After - Begin) MakeSomeGarbage() Console.ReadLine() End While End Sub
Sub MakeSomeGarbage() Dim vt As LeakingClass Dim i As Integer For i = 0 To maxGarbage - 1 vt = New LeakingClass() Next i End Sub
Sub CreateGarbage() Dim lc As LeakingClass For i As Integer = 0 To maxGarbage - 1 lc = New LeakingClass() Next i End Sub End Module
Public Class LeakingClass Public Delegate Sub StatusDel() Public Event Status As StatusDel End Class
using System; using System.Collections.Generic; using System.Text;
namespace ConsoleApplication1 { class Program { private const int maxGarbage = 1000;
static void Main() { long Begin; long After; Begin = GC.GetTotalMemory(true); Console.WriteLine("Memory used at start: {0}", Begin); // Put some objects in memory. MakeSomeGarbage(); Console.WriteLine("Memory used before collection: {0}", GC.GetTotalMemory(false));
// Collect all generations of memory. while (true) { GC.Collect(); After = GC.GetTotalMemory(false); Console.WriteLine("Memory used after full collection: {0}", GC.GetTotalMemory(true)); Console.WriteLine("Difference: {0}", After - Begin); MakeSomeGarbage(); Console.ReadLine(); } }
static void MakeSomeGarbage() { LeakingClass vt;
for (int i = 0; i < maxGarbage; i++) { // Create objects and release them to fill up memory // with unused objects. vt = new LeakingClass(); } }
} class LeakingClass { public delegate void StatusDel(); public event StatusDel Status; }
|
Memory usage - events
Denvas
Take a look at: http://support.microsoft.com/ kbid=919481. The issue is described in the KB article with more details.
Hope this helps,
dn8