2011-10-17 120 views
5

我剛開始使用ESENT ManagedInterface(http://managedesent.codeplex.com/)。我想知道它是否有內存泄漏問題。C# - ESENT db內存泄漏?

我在做什麼很簡單。我遵循示例代碼,但是我在每行中放入了一個相當大的字符串數據(10KB +),總共產生了10000行。

插入更多行時,內存使用量增加。如果我插入100,000行,程序將消耗1 GB內存並死亡。

這是代碼。

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

在上面的代碼中,它上升到大約100 MB。 只有當我做Api.JetTerm(實例)時,內存纔會被釋放

在我真正的問題中,我不得不經常插入大量數據的行很多次,所以它不會以這種方式工作,因爲內存將最終被吃掉。

任何人都可以請幫助我嗎?

**即使我提交了交易,爲什麼esent保存了內存?

我懷疑它是否存在於內存中的取消事物,如果存在,如何關閉它?我不需要撤消的事情**

感謝

P.S:我試圖在這兩個32位& 64位Windows這個test()方法,兩者具有相同的內存問題。

+0

你介意評論Eric Fleischman發佈的答案嗎?他說,你所經歷的是一個功能,而不是一個錯誤。但是你說「......節目將......並死亡。」它以什麼方式死亡? – RenniePet

回答

8

這會有幫助嗎:http://www.nikosbaxevanis.com/bonus-bits/2010/10/adventures-using-rhino-servicebus.html

Microsoft.Isam.Esent.Interop.JET_param,CacheSizeMax此參數 配置數據庫頁面緩存的最大大小。數據庫頁面大小爲 。如果此參數保留爲默認值,則 當調用JetInit時,緩存的最大大小將設置爲物理內存大小 。

設置 Microsoft.Isam.Esent.Interop.SystemParameters.CacheSizeMax 1024或 512似乎解決日益增加的內存使用量的問題。

+0

我試圖將CacheSizeMax設置爲1024或512,它仍然像以前一樣增加 – Jack

+1

是的,將它設置爲1024,我的錯誤。 – Jack

4

對不起,我遲到了這麼久黨...

我會注意,這樣做是不是固定的內存泄漏,它降低了發動機的性能。 緩存大小正在緩存內存中的數據庫頁面,因此您可以減少磁盤......就像一個好的數據庫應該一樣。 ;)如果你減少了這個,你會傷害perf並且需要更多的磁盤IO。

數據庫引擎足夠明智,可以在看到其他人使用內存時作出反應,因此從理論上講,您不應該將緩存大小設置爲這樣,如果看到其他人想要它,它將釋放內存。所以,淨,除非你真的知道你需要這樣做,我不會推薦它。