2011-10-17 4 views
5

방금 ​​ESENT ManagedInterface (http://managedesent.codeplex.com/)를 사용하기 시작했습니다. 그것이 메모리 누출 문제가 있는지 궁금합니다.C# - ESENT DB 메모리 누수가 발생 했습니까?

내가 뭘하는지는 상당히 간단합니다. 샘플 코드를 따라했지만 모든 행에 매우 큰 문자열 데이터 (10KB +)를 넣고 총 10000 개의 행을 생성합니다.

행이 삽입되는 동안 메모리 사용이 증가합니다. 만약 내가 10 만 줄처럼 삽입한다면, 프로그램은 1GB 메모리를 먹어 버리고 죽을 것이다.

다음은 코드입니다. 위의 코드에서

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가 메모리를 보유한 이유는 무엇입니까?

메모리를 보유하고있는 esent 내부의 것들을 원상태로 돌리고 있다고 생각하고 있다면, 어떻게 꺼야합니까? 나는 취소 일을하지 않아도 **

감사

P.S을 :. 둘 다 32 비트 & 64 비트 Windows에서이 테스트() 메소드를 시도, 모두 같은 메모리 문제가있다.

+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이 호출 될 때 캐시의 최대 크기가 실제 메모리의 크기로 설정됩니다. 1024 512에 Microsoft.Isam.Esent.Interop.SystemParameters.CacheSizeMax 설정

증가 메모리 사용의 문제를 해결하는 것 같다.

+0

CacheSizeMax를 1024 또는 512로 설정하려고 시도했지만, 이전처럼 계속 증가하고 있습니다. – Jack

+1

그래, 1024로 설정 했으므로 실수였습니다. – Jack

4

미안 내가 너무 늦게 파티에 난 ...

내가하는 일이 메모리 누수가 고정되지 않고 있습니다 것, 엔진의 성능을 저하입니다. 캐쉬 크기가 메모리의 캐싱 데이터베이스 페이지와 같이 디스크를 적게 걸리는 것처럼 ... 좋은 데이터베이스처럼. ;) 이것을 줄이면 퍼포먼스를 해치고 더 많은 디스크 IO를 필요로하게된다.

데이터베이스 엔진은 메모리를 사용하는 다른 사용자를 볼 때 충분히 현명하므로 이론상 사용자는 캐시 크기를 지정하지 않아야합니다. 다른 사람이 원하는 경우 메모리를 해제합니다.

정말, 당신이 정말로 이것을 할 필요가 없다면, 나는 그것을 권장하지 않습니다.

관련 문제