Hello !
Thanks to the new SDK, I built a simple HTTP server to serve pages on my Domino from a SD card. Using the HttpListener class is pretty straight forward. Or I thought so…
After serving (very well) a few pages, my application was crashing with an exception “Out of Memory”.
After a few investigations, I tend to feel that the problem is with a HttpListener class itself. Here is a very simple example to show the problem:
HttpListener Listener = new HttpListener("http", 80);
Listener.Start();
HttpListenerContext ctx;
string s;
byte[] b;
int i;
while (true)
{
ctx = Listener.GetContext();
Debug.Print("Serving a page...");
s = "<html><body>";
for (i = 0; i < 500; i++) s += "Hello!<br>"; // a 5KB dumb page
s += "</body></html>";
b = Encoding.UTF8.GetBytes(s);
ctx.Response.ContentLength64 = b.Length;
ctx.Response.ContentType = "text/html";
ctx.Response.OutputStream.Write(b, 0, b.Length);
ctx.Response.OutputStream.Close();
s = null;
b = null;
Debug.GC(true);
Debug.Print("Done with the page.");
}
Thanks to the Debug.GC(true), we see at the end of each page served that the free memory decreased. Should it ?
After serving first page:
GC: 2msec 24420 bytes used, 39960 bytes available
Type 0F (STRING ): 924 bytes
Type 11 (CLASS ): 3168 bytes
Type 12 (VALUETYPE ): 552 bytes
Type 13 (SZARRAY ): 1956 bytes
Type 15 (FREEBLOCK ): 39960 bytes
Type 16 (CACHEDBLOCK ): 60 bytes
Type 17 (ASSEMBLY ): 14328 bytes
Type 18 (WEAKCLASS ): 48 bytes
Type 19 (REFLECTION ): 24 bytes
Type 1B (DELEGATE_HEAD ): 288 bytes
Type 1D (OBJECT_TO_EVENT ): 96 bytes
Type 1E (BINARY_BLOB_HEAD ): 156 bytes
Type 1F (THREAD ): 384 bytes
Type 20 (SUBTHREAD ): 48 bytes
Type 21 (STACK_FRAME ): 480 bytes
Type 22 (TIMER_HEAD ): 72 bytes
Type 27 (FINALIZER_HEAD ): 96 bytes
Type 31 (IO_PORT ): 108 bytes
Type 34 (APPDOMAIN_HEAD ): 72 bytes
Type 36 (APPDOMAIN_ASSEMBLY ): 1560 bytes
After serving second page:
GC: 2msec 27684 bytes used, 36696 bytes available
Type 0F (STRING ): 1812 bytes
Type 11 (CLASS ): 4632 bytes
Type 12 (VALUETYPE ): 552 bytes
Type 13 (SZARRAY ): 2880 bytes
Type 15 (FREEBLOCK ): 36696 bytes
Type 17 (ASSEMBLY ): 14328 bytes
Type 18 (WEAKCLASS ): 48 bytes
Type 19 (REFLECTION ): 24 bytes
Type 1B (DELEGATE_HEAD ): 288 bytes
Type 1D (OBJECT_TO_EVENT ): 96 bytes
Type 1E (BINARY_BLOB_HEAD ): 156 bytes
Type 1F (THREAD ): 384 bytes
Type 20 (SUBTHREAD ): 48 bytes
Type 21 (STACK_FRAME ): 480 bytes
Type 22 (TIMER_HEAD ): 72 bytes
Type 27 (FINALIZER_HEAD ): 144 bytes
Type 31 (IO_PORT ): 108 bytes
Type 34 (APPDOMAIN_HEAD ): 72 bytes
Type 36 (APPDOMAIN_ASSEMBLY ): 1560 bytes
After serving third page:
GC: 3msec 29508 bytes used, 34872 bytes available
Type 0F (STRING ): 1920 bytes
Type 11 (CLASS ): 5508 bytes
Type 12 (VALUETYPE ): 552 bytes
Type 13 (SZARRAY ): 3672 bytes
Type 15 (FREEBLOCK ): 34872 bytes
Type 17 (ASSEMBLY ): 14328 bytes
Type 18 (WEAKCLASS ): 48 bytes
Type 19 (REFLECTION ): 24 bytes
Type 1B (DELEGATE_HEAD ): 288 bytes
Type 1D (OBJECT_TO_EVENT ): 96 bytes
Type 1E (BINARY_BLOB_HEAD ): 156 bytes
Type 1F (THREAD ): 384 bytes
Type 20 (SUBTHREAD ): 48 bytes
Type 21 (STACK_FRAME ): 480 bytes
Type 22 (TIMER_HEAD ): 72 bytes
Type 27 (FINALIZER_HEAD ): 192 bytes
Type 31 (IO_PORT ): 108 bytes
Type 34 (APPDOMAIN_HEAD ): 72 bytes
Type 36 (APPDOMAIN_ASSEMBLY ): 1560 bytes
etc, etc etc.
We see after each page that the values “CLASS” and “SZARRAY” keep increasing.
Just to make sure that was not something else, and because I am fairly new with C# (but not with programming… 20+ years experience), I built another simple test, doing almost the same, just not using the class:
Debug.GC(true);
string s;
byte[] b;
int i;
while (true)
{
Debug.Print("Serving a page...");
s = "<html><body>";
for (i = 0; i < 500; i++) s += "Hello!<br>"; // a 5KB dumb page
s += "</body></html>";
b = Encoding.UTF8.GetBytes(s);
s = null;
b = null;
Debug.GC(true);
Debug.Print("Done with the page.");
Thread.Sleep(10000);
}
Then, of course, we get the same amount of free memory after each run.
So : What am I doing wrong ?
Thank you in advance !
Nicolas