2011-10-17 16 views
5

ESENT ManagedInterface'i kullanmaya başladım (http://managedesent.codeplex.com/). Bir bellek sızıntısı sorunu olup olmadığını merak ediyorum.C# - ESENT db bellek sızıntısı var mı?

Yaptığım şey oldukça basit. Örnek kod takip ettim, ancak her satırda oldukça büyük bir dize verisi (10 KB +) koydum ve toplamda 10000 satır ürettim.

Daha fazla satır eklenirken bellek kullanımı artar. 100.000 satır gibi eklerseniz, program 1 GB bellek tüketir ve ölür.

İşte kod. Yukarıdaki kodda

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"); 
    } 

, yaklaşık 100 MB'a kadar gider. Yalnızca Api.JetTerm (örnek) yaptığımda, bellek serbest bırakıldı.

Benim asıl sorunumda, sürekli olarak çok miktarda veriyi birçok kez eklemek zorundayım, bu yüzden bu şekilde benim için çalışmayacak, çünkü bellek sonunda yenecek.

Bu konuda bana yardımcı olabilecek herhangi biri olabilir mi?

** İşlemi gerçekleştirmeme rağmen neden bellekte bellek var?

İçinde hafızayı tutan özün içindeki şeylerin olduğu şüphesi var, eğer öyleyse, nasıl kapatılır? Ben geri alma şeye ihtiyacım yok **

Teşekkür

P.S.:. Ben hem 32bit & 64bit, Windows içinde bu test() yöntemini denedik, her ikisi de aynı hafıza sorunu var olması.

+0

Eric Fleischman'ın gönderdiği cevaba yorum yazabilir misiniz? Yaşadıklarınızın bir özellik değil, bir hata olduğunu söylüyor. Ama sen diyorsun ki ... program ... ve ölür. Hangi şekilde öldü? – RenniePet

cevap

8

Bu herhangi bir kullanıcıyla karşılaşırdı: http://www.nikosbaxevanis.com/bonus-bits/2010/10/adventures-using-rhino-servicebus.html?

Microsoft.Isam.Esent.Interop.JET_param, CacheSizeMax Bu parametre veritabanı sayfası önbelleği maksimum boyutunu yapılandırır. Boyut veritabanı sayfalarındadır. Bu parametre varsayılan değerine bırakılırsa,önbelleğin maksimum boyutu, JetInit çağrıldığında fiziksel belleğin boyutuna ayarlanacaktır. 1024 veya Microsoft.Isam.Esent.Interop.SystemParameters.CacheSizeMax Ayar

artan bellek kullanımı ile sorunu çözmek gibi görünüyor.

+0

1024 veya 512'ye CacheSizeMax'i ayarlamaya çalıştım, hala – Jack

+1

'dan önce olduğu gibi artıyor, 1024'e ayarlıyım, benim hatam. – Jack

4

Üzgünüm geç partiye değilim ...

yaptığım bu bellek sızıntısına sabitleme unutmayın ediyorum, bu motorun performansını azaltan ediyor. Önbellek boyutu, bellekte veritabanı sayfalarını önbelleğe almaktır, böylece diske daha az vurursunuz ... tıpkı iyi bir veritabanı gibi. ;) Bunu düşürürseniz, mükemmel davranırsınız ve daha fazla disk IO gerektirir.

Veritabanı motoru, bellek kullanan diğer kişileri gördüğünde geri çekilecek kadar akıllıcadır, bu nedenle, teoride, önbellek boyutuna sahip olmamalıdır, başkalarını istediğini görürse bellek serbest bırakılır.

Yani, net, bunu gerçekten bilmeniz gerekmedikçe, bunu tavsiye etmem.