views:

385

answers:

3

I'm developing a Desktop Search Engine in VB9 (VS2008).

Is it normal for a Service to take up 9MB of Memory while the only Thread involved in the Service is sleeping?

The code includes following import statements...

Imports System
Imports System.IO
Imports Microsoft.Win32
Imports System.Threading

There are a few class variables in the Service class

Private serviceStarted As Boolean = False
Dim workerThread As Thread
Dim DSEKey As RegistryKey
Dim indexFolder As String
Dim tempFolder As String
Dim docFolders As String()
Dim interval As Integer

The OnStart method takes the following form:

protected override void OnStart(string[] args)
{

   ThreadStart st = new ThreadStart(WorkerFunction);
   workerThread = new Thread(st);

    serviceStarted = true;

    workerThread.Start();
}

The WorkerFunction takes the following form:

private void WorkerFunction()
{

   while (serviceStarted)
   {

      // Desired function - STARTS

      // Desired function - ENDS

      // Close all open objects

      if (serviceStarted)
      {
         Thread.Sleep(new TimeSpan(0, interval, 0);
      }
   }

   Thread.CurrentThread.Abort();
}

Process Explorer describes Physical memory usage as:

Working Set: 9,440 K
    WS Private:   2,356 K
    WS Shareable: 7,084 K
    WS Shared:    6,440 K

Is this normal or am I doing something wrong?

+2  A: 

From that I can tell from that memory usage you are using only about 2.3 mb of actual memory, the shared/sharable set is essentially a "cached" collection of memory, meaning that the app has earmarked it just incase it needs it.

Your application memory usage is most likely not that bad considering that you do have a number of private members that are going to take up some memory.

I most likely wouldn't be concerned about it, however, if you are looking to really optimize and identify the source of the memory usage you might use ANTS Profiler from RedGate to investigate the individual objects in memory.

Mitchel Sellers
+1  A: 

Allow me to preface this with a) I know nothing about VB, and b) I know little about the windows memory model. However, if I saw this on a linux system, I'd say you only need to be concerned about the Private memory usage. The shared/shareable stuff is most likely DLLs loaded by the VB (.net?) runtime, and not a concern, since they're shared between apps. 2MB doesn't seem overly huge for a VB app, even one that doesn't have much data. If it was a C++ app, I'd be concerned, but for an interpreted language, I think it's about par for the course. I assume it's mostly overhead, not actually split among your few variables. Also, are you running a debug or release build? That could seriously impact the memory footprint.

Just my $0.02. Take with a large grain of salt, as I may be entirely off base.

EDIT: I forgot to mention originally that it shouldn't matter if your thread is awake or sleeping. Unless the system is low on memory, it's not going to page out the memory of a sleeping thread, and even then who knows what algorithm it uses (and if it is low on memory, it may also page out running threads...). Also, even if it is paged out, it will still show up as memory used (though since you said that's the physical memory measurement, it probably would show up somewhere else).

rmeador
+2  A: 

This is caused by the CLR/GC and Windows Memory Manager negotiating memory. The CLR/GC will allocate more memory than it needs from windows making the workingset appear high. However, if the Windows Memory Manager (at the OS level) detects that more memory is needed it will attempt to get more memory from your application's process as needed. Now, if you want to force that working set to go low you can try setting the Porcess.MaxWorkingSet property to -1. This instructs windows to immediately try to "trim the workingset" to the minimum amount of memory possible. Alternatively you can use the corresponding Windows API SetProcessWorkingSetSize.

However, the drawbacks are that this requires some higher permissions (FullTrust for Working Set, and Unmanaged/P/Invoke access for SetProcessWorkingSetSize) and that the CLR may allocate memory slower next time it needs memory since it will have to go back to the OS to get more memory.

BTW: You can see evidence of this behavior in the MSDN documentation for the underlying corresponding Windows API SetProcessWorkingSetSize. Note the point that reads:

If both dwMinimumWorkingSetSize and dwMaximumWorkingSetSize have the value (SIZE_T)–1, the function removes as many pages as possible from the working set of the specified process.

scott