Leaking Retina.Configuration.ConfigurationRetreiver

Sep 15, 2009 at 1:05 PM

Hi,

my application is leaking instances of Retina.Configuration.ConfigurationRetreiver. I haven't pinned down the exact circumstances that are leading to the leak, except that it happens during read/write operations. Profiling a simpler Retina app doesn't yield any ConfigurationRetreiver instances - so when exactly does this type get created. Anyone?

Coordinator
Sep 16, 2009 at 2:09 AM
Edited Sep 16, 2009 at 2:09 AM

Hi, I have done extensive memory leak analysis on Retina.NET and in some applications using it without finding anything significant.

Every class used for read and memory storage of configuration are static, so you might find some rooted instances using a memory analysis tool but those aren't leaks.

One of the applications where Retina.NET is being used runs several thousands database transactions per second (I'm not exagerating here) and we haven't found memory leaks, so any information about what you have found would be very important.

Some details about the tool used for profiling, captured numbers / dumps, screenshots, test code, etc, that could help detect and eliminate any memory leak wil be greatly appreciated.

Thanks in advance,

Andrés.

Sep 17, 2009 at 10:09 AM

Hi,

I just finished running a pair of tests where I carried out 10,000 read/write operations.

Profiler: YourKit Profiler 4.5.3          

In the frist test my application didn't have an app.config file. I ran the test and there was no evidence of memory leakage and no instances of Retina.Configuration.ConfigurationRetreiver were created.

In the 2nd test I added an app.config file to the test application and performed 10,000 read/write operations as before. The application leaked about 130MB and created 20,000 instances of Retina.Configuration.ConfigurationRetreiver [1 for each read and 1 for each write operation]. Forcing garbage collection had no effect.

 

The test function:

Private Sub btGo_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btGo.Click

        Dim nCount, nCycles As Integer

        Try
            nCycles = Integer.Parse(txtCycles.Text)
        Catch ex As Exception
            nCycles = 1
        End Try

        For nCount = 1 To nCycles

            txtLog.AppendText("Start Cycle:" & nCount.ToString & vbCrLf)

            Dim ds As New SqlDataStore(txtCon.Text)
            Dim brk As New Retina.DataStoreBrokers.Department.DataStoreBroker(ds)
            Dim inv As InvoiceHeader

            inv = brk.Retrieve(GetType(InvoiceHeader), "100100")

            If inv Is Nothing = False Then
                txtLog.AppendText("Read ok" + vbCrLf)

                inv = brk.Persist(inv)

                If inv Is Nothing = False Then
                    txtLog.AppendText("Save ok" + vbCrLf)
                Else
                    txtLog.AppendText("Save failed" + vbCrLf)

                    Exit Sub
                End If

            Else
                txtLog.AppendText("Read failed...check setup" + vbCrLf)
                Exit Sub
            End If

            Application.DoEvents()
        Next

    End Sub

Coordinator
Sep 17, 2009 at 12:07 PM

A couple more questions....  

1) is this a Web or Forms application?

2) The Retina config section is read from an app.config file or Retina.config file?

The recommended approach is to have a separated Retina.config file and not to include the RetinaConfiguration section within an existing web.config or app.config file. This is the configuration we are using (and tested for leaks) without problems.

Anyway, I'm going to run some more tests and see what happens.

Thanks a lot for your time,

Andrés.

Coordinator
Sep 17, 2009 at 12:35 PM

Instances for Retina.Configuraiton.ConfigurationRetriever are only created in one place, and stored statically within the current AppDomain. The code that does that is the following:

public static object GetConfig(string sectionName) {

   ConfigurationRetriever retriever = (ConfigurationRetriever)AppDomain.CurrentDomain.GetData(AppKey + "ConfigurationRetriever");

   if (retriever == null)

      retriever = new ConfigurationRetriever(ConfigurationDocument);

      AppDomain.CurrentDomain.SetData(AppKey + "ConfigurationRetriever", retriever);

   }

   return retriever.GetConfig(sectionName);

}

 

Will keep investigating....

Andrés.

Sep 17, 2009 at 2:16 PM

 

1. Its a Forms app.

2. There is no Retina-specific config in the config file; all you have to do is add a config file to the project to get the leak going.

 

 

Coordinator
Sep 17, 2009 at 3:24 PM

Oh, well, I understand what's happening now....

Retina.NET REQUIRES a configuration section, so using it like this is a non tested scenario. Having said that, I could modify Retina.NET to support this particular scenario without leaking those instances.

What happens is that Retina.NET tryies to read configuration but there is no configuration file or section anywhere, so the configuraiton reader keep returning NULL and therefore the configuration manager keep thinking that configuration is still unread, In that case, it will try to read configuration again (creating the offending instance of the Retina.Configuraiton.ConfigurationRetriever class) and therefore this new instance will be leaked.

As a workaround you could create a dummy Retine.config or RetinaConfigSettings section in your config and the leak will dissapear.

The permanent solution would be to check on a flag that indicates if configuration was already read instead of only checking for configuration values.

Hope this helps,

Andrés.

Sep 17, 2009 at 8:09 PM

Thanks Andrés,

this helps a lot.

 

Coordinator
Sep 23, 2009 at 12:44 PM
This discussion has been copied to a work item. Click here to go to the work item and continue the discussion.