2011-10-17 10 views
5

Acabo de empezar a utilizar ESENT ManagedInterface (http://managedesent.codeplex.com/). Me pregunto si tiene un problema de pérdida de memoria.C# - ESENT db memory leaks?

Lo que estoy haciendo es bastante simple. Seguí el código de muestra, pero puse una cadena de datos bastante grande (10 KB +) en cada fila y produzco 10000 filas en total.

El uso de memoria aumenta a medida que se insertan más filas. Si inserto como 100.000 filas, el programa consumirá 1 GB de memoria y morirá.

Aquí está el código.

public static void test() 
    { 
     string techcrunchString = @"The Latest from TechCrunch CMU Researchers Turn Any Surface Into A TouchscreenWeb Design Community Treehouse Raises $600K From Reid Hoffman, Kevin Rose, And Others Greylock Looks To Help Portfolio Companies Recruit Talent With New Hires UberMedia Quietly (Inadvertently?) Releases Chime.in, A Mobile Social Networking App T-Mobile Announces The Dual-Screen LG DoublePlay, Launching November 2nd? Watch An iPhone 4S and Samsung Galaxy S II Take Three Nasty Drops Onto Concrete Facebook, NRDC & Opower To Partner On Energy-Saving Social AppCTIAs New Alert Guidelines Could Mean The End Of Bill ShockGrockit Gets A $7 Million Venture Infusion And Launches Video Q&A Site Grockit AnswersGorgeous Photos, Tablet Browsing: 500px Debuts New iPad AppSamsung Galaxy Nexus, HTC Vigor To Launch November 10?Freelance.com: Facebook App, 3D, HTML5, And Cocoa Jobs On The RiseiPhone 4S First Weekend Sales Exceeds 4 Million, Doubles The Pace Of The iPhone 4Wahanda Secures $5.5 Million From Fidelity Growth Partners EuropeLook Out Uber: GroundLink Launches An Affordable, Mobile Private Car Service For New YorkersVideo Collaboration Software Maker ViVu Acquired By PolycomWith 400,000 Users Under Its Belt, SohoOS Plans Major Revamp5 Product Innovations From CEATEC 2011 In Japan (Video Gallery)Digital Media Companies Inuvo And Vertro To MergeRIM Apologizes With Free Apps & Technical Support For Three Days Of DowntimeCMU Researchers Turn Any Surface Into A TouchscreenPosted: 17 Oct 2011 09:14 AM PDT"; 

     JET_INSTANCE instance; 
     JET_SESID sesid; 
     JET_DBID dbid; 
     JET_TABLEID tableid; 

     JET_COLUMNDEF columndef = new JET_COLUMNDEF(); 

     // Initialize ESENT. Setting JET_param.CircularLog to 1 means ESENT will automatically 
     // delete unneeded logfiles. JetInit will inspect the logfiles to see if the last 
     // shutdown was clean. If it wasn't (e.g. the application crashed) recovery will be 
     // run automatically bringing the database to a consistent state. 
     Api.JetCreateInstance(out instance, "instance"); 
     Api.JetSetSystemParameter(instance, JET_SESID.Nil, JET_param.CircularLog, 1, null); 
     Api.JetInit(ref instance); 
     Api.JetBeginSession(instance, out sesid, null, null); 

     // Create the database. To open an existing database use the JetAttachDatabase and 
     // JetOpenDatabase APIs. 
     Api.JetCreateDatabase(sesid, "edbtest.db", null, out dbid, CreateDatabaseGrbit.OverwriteExisting); 

     // Create the table. Meta-data operations are transacted and can be performed concurrently. 
     // For example, one session can add a column to a table while another session is reading 
     // or updating records in the same table. 
     // This table has no indexes defined, so it will use the default sequential index. Indexes 
     // can be defined with the JetCreateIndex API. 
     Api.JetBeginTransaction(sesid); 
     Api.JetCreateTable(sesid, dbid, "table", 0, 100, out tableid); 

     JET_COLUMNID id; 
     columndef.coltyp = JET_coltyp.Binary; 
     columndef.cp = JET_CP.ASCII; 
     Api.JetAddColumn(sesid, tableid, "id", columndef, null, 0, out id); 

     JET_COLUMNID blob; 
     columndef.coltyp = JET_coltyp.LongBinary; 
     //columndef.cp = JET_CP.ASCII; 
     Api.JetAddColumn(sesid, tableid, "blob", columndef, null, 0, out blob); 

     string indexDef = "+id\0\0"; 
     Api.JetCreateIndex(sesid, tableid, "primary", CreateIndexGrbit.IndexPrimary, indexDef, indexDef.Length, 100); 
     //Api.JetSetCurrentIndex(sesid, tableid, null); 
     Api.JetCommitTransaction(sesid, CommitTransactionGrbit.LazyFlush); 

     long Process_MemoryStart = 0; 
     Process MyProcess = System.Diagnostics.Process.GetCurrentProcess(); 
     Process_MemoryStart = MyProcess.PrivateMemorySize64; 
     Console.WriteLine("Before loop : " + Process_MemoryStart/1024 + "KB"); 

     int i = 0; 
     for (int t = 0; t < 20; t++) 
     { 
      Api.JetBeginTransaction(sesid); 
      for (int j = 0; j < 500; j++) 
      { 
       i = t * 500 + j; 
       string dataString = techcrunchString + i.ToString(); 

       byte[] data = Encoding.UTF8.GetBytes(dataString); 
       string keyString = i.ToString(); 
       byte[] key = Encoding.UTF8.GetBytes(keyString); 

       //store 
       Api.MakeKey(sesid, tableid, key, MakeKeyGrbit.NewKey); 
       bool exists = Api.TrySeek(sesid, tableid, SeekGrbit.SeekEQ); 

       if (exists) 
       { 
        Api.JetPrepareUpdate(sesid, tableid, JET_prep.ReplaceNoLock); 
        //Console.WriteLine("store: " + "update"); 
       } 
       else 
       { 
        Api.JetPrepareUpdate(sesid, tableid, JET_prep.Insert); 
        Api.SetColumn(sesid, tableid, id, key); 
        //Console.WriteLine("store: " + "insert"); 
       } 
       Api.SetColumn(sesid, tableid, blob, data); 
       Api.JetUpdate(sesid, tableid); 

       if (i % 500 == 0) 
       { 
        long Process_MemoryStart1 = 0; 
        Process MyProcess1 = System.Diagnostics.Process.GetCurrentProcess(); 
        Process_MemoryStart1 = MyProcess1.PrivateMemorySize64; 
        Console.WriteLine("Finished " + i.ToString() + " : " + Process_MemoryStart1/1024 + "KB"); 

       } 

      } 
      Api.JetCommitTransaction(sesid, CommitTransactionGrbit.None); 


     } 
     Process_MemoryStart = 0; 
     MyProcess = System.Diagnostics.Process.GetCurrentProcess(); 
     Process_MemoryStart = MyProcess.PrivateMemorySize64; 
     Console.WriteLine("Loop finished: " + Process_MemoryStart/1024 + "KB"); 

     // Terminate ESENT. This performs a clean shutdown. 
     Api.JetCloseTable(sesid, tableid); 
     Process_MemoryStart = 0; 
     MyProcess = System.Diagnostics.Process.GetCurrentProcess(); 
     Process_MemoryStart = MyProcess.PrivateMemorySize64; 
     Console.WriteLine("After close table: " + Process_MemoryStart/1024 + "KB"); 

     Api.JetEndSession(sesid, EndSessionGrbit.None); 
     Process_MemoryStart = 0; 
     MyProcess = System.Diagnostics.Process.GetCurrentProcess(); 
     Process_MemoryStart = MyProcess.PrivateMemorySize64; 
     Console.WriteLine("After end session: " + Process_MemoryStart/1024 + "KB"); 

     Api.JetTerm(instance); 

     Process_MemoryStart = 0; 
     MyProcess = System.Diagnostics.Process.GetCurrentProcess(); 
     Process_MemoryStart = MyProcess.PrivateMemorySize64; 
     Console.WriteLine("After term instance: " + Process_MemoryStart/1024 + "KB"); 
    } 

En el código anterior, asciende a alrededor de 100 MB. Solo si lo hago Api.JetTerm (instancia), la memoria se libera.

En mi problema real, tengo que insertar constantemente filas de gran cantidad de datos muchas veces, por lo que no funcionará para mí de esta manera, ya que la memoria finalmente se consumirá.

¿Alguien podría ayudarme con esto?

** ¿Por qué esent conserva la memoria incluso si he realizado la transacción?

Estoy sospechando que es el deshacer las cosas dentro de esent que contiene la memoria, y si es así, ¿cómo desactivarla? No necesito que deshacer **

Gracias

P.S:. He intentado este método de ensayo() tanto en 32 bits & Windows de 64 bits, ambos tiene el mismo problema de memoria.

+0

¿Te importaría comentar la respuesta publicada por Eric Fleischman? Él dice que lo que has experimentado es una característica, no un error. Pero dices "... el programa ... y se muere". ¿De qué manera murió? – RenniePet

Respuesta

8

Sería de alguna ayuda: http://www.nikosbaxevanis.com/bonus-bits/2010/10/adventures-using-rhino-servicebus.html?

Microsoft.Isam.Esent.Interop.JET_param, CacheSizeMax Este parámetro configura el tamaño máximo de la base de datos de la página de caché. El tamaño está en páginas de la base de datos. Si este parámetro se deja en su valor predeterminado, entonces el tamaño máximo de la memoria caché se establecerá en el tamaño de la memoria física cuando se invoque JetInit.

Ajuste del Microsoft.Isam.Esent.Interop.SystemParameters.CacheSizeMax a 1024 o 512 parece resolver el problema con el uso de la memoria cada vez mayor.

+0

He intentado configurar CacheSizeMax a 1024 o 512, sigue aumentando al igual que antes – Jack

+1

Sí, configúralo a 1024, mi error. – Jack

4

Siento llegar tan tarde a la fiesta ...

me gustaría tener en cuenta que al hacer esto no es la fijación de una pérdida de memoria, que está reduciendo el rendimiento del motor. El tamaño de la memoria caché almacena en la memoria caché las páginas de la base de datos de modo que golpee menos el disco ... como una buena base de datos. ;) Si reduce esto, está perjudicando el rendimiento y necesitando más disco IO.

El motor de base de datos es lo suficientemente inteligente como para retroceder cuando ve a otras personas usando memoria, por lo que en teoría no debería tener el tamaño de caché como este, liberará memoria si otros lo desean.

Así que, neto, a menos que realmente sepa que necesita hacer esto, no lo recomendaría.