none
Problemas com memória RRS feed

  • Pergunta

  • Tenho problemas de um consumo de memória cumulativo e progressivo em sistemas desenvolvidos em .NET.

    Por exemplo, eu testei 2 maneiras diferentes:

    Usando os objetos como Shared para todas as classes de regras de negócios, parece acumular mais memória.

    Instanciando e setando para nothing os objetos necessários em cada método, acumula memória tbm, mas de uma maneira menos intensa.

    Há alguma maneira mais aconselhável (ou ideal) de se usar os objetos? (Notadamente os Datatables, DataReaders, Parameters, Command, Connection e Adapter)

    O Garbage Collector não deveria cuidar desse problema todo?

     

    quarta-feira, 17 de maio de 2006 14:58

Respostas

  • Felipe,

    você está fechando todas as conexões?

    Veja algumas discussões sobre chamar ou não explicitamente o Garbage Collector:

    C# Tip: Forcing Garbage Collection in .NET - http://www.developer.com/net/csharp/article.php/3343191
    .NET GC Best Practice -- ALWAYS Call Dispose  - http://weblogs.asp.net/pwilson/archive/2004/02/20/77435.aspx
    Dispose and close or close without dispose - http://weblogs.asp.net/pleloup/archive/2004/02/03/66623.aspx
    ADO.NET Database connections - Close() Vs. Dispose() - http://codebetter.com/blogs/sahil.malik/archive/2004/12/31/40036.aspx

    quarta-feira, 17 de maio de 2006 15:01
  • Felipe,

        Quando você seta uma variável para Nothing (null no C#), você não faz com que a classe libere os recurso alocados por ela, você só mata a instancia dela, mas os recursos continuam alocados por ela.

    Acho que em VB.Net também existe a diretiva using. Ela chama o método dispose, caso a classe implemente a interface IDisposable, após um bloco de execução. Um exemplo simples:

    using ( SqlConnection cn = new SqlConnection(connectionString) )
    {
           cn.Open();
       
           using ( SqlCommand cmd = new SqlCommand() )
            {
                 cmd.CommandText = "";
                 cmd.CommandType = "";
                 cmd.ExecuteNonQuery();
            }
    }

    Desculpa se o exemplo é em C#, é que eu to mais acostumado com a linguagem. :)

    Bom espero que ajude.

    []´s

    Thiago Oliveira
    sexta-feira, 19 de maio de 2006 17:49
  • Felipe,

    O Garbage Collector cuida disso desde que você solicite que ele o faça.

    objetoconnection.Dispose () ;

    Faz com que o objeto seja colocado à disposição da coleta de lixo.

    Você pode pensar em configurar o seu servidor com pool de conexões.

    Não conheço a arquitetura do seu sistema, mas onde você diz que usou objetos shared, o ideal não seria Static ? Pq o Static é instanciado só uma vez, vc não usa o new.

    quarta-feira, 24 de maio de 2006 19:16

Todas as Respostas

  • Felipe,

    você está fechando todas as conexões?

    Veja algumas discussões sobre chamar ou não explicitamente o Garbage Collector:

    C# Tip: Forcing Garbage Collection in .NET - http://www.developer.com/net/csharp/article.php/3343191
    .NET GC Best Practice -- ALWAYS Call Dispose  - http://weblogs.asp.net/pwilson/archive/2004/02/20/77435.aspx
    Dispose and close or close without dispose - http://weblogs.asp.net/pleloup/archive/2004/02/03/66623.aspx
    ADO.NET Database connections - Close() Vs. Dispose() - http://codebetter.com/blogs/sahil.malik/archive/2004/12/31/40036.aspx

    quarta-feira, 17 de maio de 2006 15:01
  • Ricardo,

    Passar o connection para Nothing (cnn = nothing) não teria a mesma funcionalidade de cnn.close?

    Na verdade, eu dei uma olhada no código, e eu dou o Close, e ainda dou o =nothing.

    Em datareaders tbm faço a mesma coisa.

    Eu isolei tudo referente a acesso a dados em uma camada da aplicação, estou te enviando um exemplo de Função que usa manipulação de dados. Pode me sugerir alguma otimização?

     

    Public Overloads Function ExecutarSQLScalar(ByVal vSQL As String, ByVal vParametro As IDbDataParameter, Optional ByVal vCommandType As CommandType = CommandType.Text) As Object

    mParams.PrepararParametros(vParametro, mDBINI.CMD)
    mInnerCall = True
    Return ExecutarSQLScalar(vSQL, vCommandType)

    End Function

     

    Private Sub LimparDBLib()
    CNX.Close()
    CNX = Nothing
    CMD = Nothing
    DA = Nothing

    End Sub

    Public Overloads Function ExecutarSQLScalar(ByVal vSQL As String, ByVal vParametros As IDbDataParameter(), Optional ByVal vCommandType As CommandType = CommandType.Text) As Object

    mParams.PrepararParametros(vParametros, mDBINI.CMD)
    mInnerCall = True
    Return ExecutarSQLScalar(vSQL, vCommandType)

    End Function

    Public Overloads Function ExecutarSQLScalar(ByVal vSQL As String, Optional ByVal vCommandType As CommandType = CommandType.Text) As Object

    Try

    If mInnerCall = False Then mParams.LimparParametros(mDBINI.CMD)
    If Transacao = False Then mDBINI.CNX.Open()
    mDBINI.CMD.CommandType = vCommandType
    mDBINI.CMD.CommandText = vSQL
    ExecutarSQLScalar = mDBINI.CMD.ExecuteScalar()
    Catch ex As Exception
    Throw New DBLibException("ExecutarSQLScalar: " & ex.Message, ex)
    ExecutarSQLScalar = Nothing
    Finally

    If Transacao = False Then mDBINI.CNX.Close()
    mInnerCall = False
    End Try

    End Function

     Protected Overrides Sub Finalize()
    LimparDBLib()
    End Sub

    Private Sub LimparDBLib()
    CNX = Nothing ' Connection
    CMD = Nothing 'Command
    DA = Nothing 'Adapter
    End Sub

    quarta-feira, 17 de maio de 2006 15:26
  • Felipe,

        Quando você seta uma variável para Nothing (null no C#), você não faz com que a classe libere os recurso alocados por ela, você só mata a instancia dela, mas os recursos continuam alocados por ela.

    Acho que em VB.Net também existe a diretiva using. Ela chama o método dispose, caso a classe implemente a interface IDisposable, após um bloco de execução. Um exemplo simples:

    using ( SqlConnection cn = new SqlConnection(connectionString) )
    {
           cn.Open();
       
           using ( SqlCommand cmd = new SqlCommand() )
            {
                 cmd.CommandText = "";
                 cmd.CommandType = "";
                 cmd.ExecuteNonQuery();
            }
    }

    Desculpa se o exemplo é em C#, é que eu to mais acostumado com a linguagem. :)

    Bom espero que ajude.

    []´s

    Thiago Oliveira
    sexta-feira, 19 de maio de 2006 17:49
  • Felipe,

    O Garbage Collector cuida disso desde que você solicite que ele o faça.

    objetoconnection.Dispose () ;

    Faz com que o objeto seja colocado à disposição da coleta de lixo.

    Você pode pensar em configurar o seu servidor com pool de conexões.

    Não conheço a arquitetura do seu sistema, mas onde você diz que usou objetos shared, o ideal não seria Static ? Pq o Static é instanciado só uma vez, vc não usa o new.

    quarta-feira, 24 de maio de 2006 19:16