2011-10-17 45 views
5

Tôi mới bắt đầu sử dụng ESENT ManagedInterface (http://managedesent.codeplex.com/). Tôi tự hỏi liệu nó có vấn đề rò rỉ bộ nhớ hay không.C# - rò rỉ bộ nhớ db ESENT?

Điều tôi đang làm khá đơn giản. Tôi theo mã mẫu, nhưng tôi đặt một chuỗi dữ liệu khá lớn (10KB +) trong mỗi hàng và tạo ra tổng cộng 10000 hàng.

Mức sử dụng bộ nhớ tăng lên khi có thêm hàng. Nếu tôi chèn như 100.000 hàng, chương trình sẽ ăn bộ nhớ 1 GB và chết.

Đây là mã.

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

Ở mã trên, tăng lên tới khoảng 100 MB. Chỉ khi tôi làm Api.JetTerm (ví dụ), bộ nhớ được giải phóng.

Trong vấn đề thực sự của mình, tôi phải liên tục chèn các hàng dữ liệu lớn nhiều lần, vì vậy nó sẽ không hoạt động cho tôi theo cách này vì cuối cùng bộ nhớ sẽ được ăn hết.

Có ai vui lòng giúp tôi với điều này không?

** Tại sao esent giữ bộ nhớ ngay cả khi tôi cam kết giao dịch?

Tôi nghi ngờ đó là những điều hoàn tác bên trong esent chứa bộ nhớ, và nếu có, làm thế nào để tắt nó đi? Tôi không cần điều undo **

Cảm ơn

Tái bút:. Tôi đã thử phương pháp thử nghiệm() này trong cả 32bit & 64bit Windows, cả hai có vấn đề bộ nhớ tương tự.

+0

Bạn có nhớ nhận xét về câu trả lời được đăng bởi Eric Fleischman không? Anh ấy nói rằng những gì bạn đã trải nghiệm là một tính năng, không phải là một lỗi. Nhưng bạn nói "... chương trình sẽ ... và chết." Bằng cách nào nó chết? – RenniePet

Trả lời

8

Đây có phải là sự giúp đỡ nào không: http://www.nikosbaxevanis.com/bonus-bits/2010/10/adventures-using-rhino-servicebus.html?

Microsoft.Isam.Esent.Interop.JET_param, CacheSizeMax Tham số này định cấu hình kích thước tối đa của bộ đệm trang cơ sở dữ liệu. Kích thước nằm trong các trang cơ sở dữ liệu . Nếu tham số này được để giá trị mặc định của nó, thì kích thước tối đa của bộ nhớ cache sẽ được đặt thành kích thước của bộ nhớ vật lý khi JetInit được gọi.

Thiết lập Microsoft.Isam.Esent.Interop.SystemParameters.CacheSizeMax 1024 hoặc 512 dường như giải quyết vấn đề với việc sử dụng bộ nhớ ngày càng tăng.

+0

Tôi đã cố gắng đặt CacheSizeMax thành 1024 hoặc 512, nó vẫn đang tăng giống như trước – Jack

+1

Vâng, đặt thành 1024 làm việc, lỗi của tôi. – Jack

4

Xin lỗi Tôi rất muộn để đảng ...

tôi muốn lưu ý rằng việc này không được sửa chữa rò rỉ bộ nhớ, nó làm giảm hiệu suất của động cơ. Kích thước bộ đệm ẩn là các trang cơ sở dữ liệu đệm trong bộ nhớ sao cho bạn nhấn đĩa ít hơn ... giống như một cơ sở dữ liệu tốt nên. ;) Nếu bạn giảm này bạn đang làm tổn thương perf và đòi hỏi nhiều đĩa IO.

Công cụ cơ sở dữ liệu đủ khôn ngoan để quay trở lại khi thấy người khác sử dụng bộ nhớ, vì vậy lý thuyết bạn không nên có kích thước bộ nhớ cache như thế này, nó sẽ giải phóng bộ nhớ nếu nó thấy người khác muốn.

Vì vậy, mạng, trừ khi bạn thực sự biết bạn cần phải làm điều này, tôi sẽ không khuyên bạn nên nó.