C# - ESENT db内存泄漏?

Jac*_*ack 5 c# memory-leaks esent

我刚开始使用ESENT ManagedInterface(http://managedesent.codeplex.com/).我想知道它是否有内存泄漏问题.

我正在做的很简单.我按照示例代码,但是我在每一行中放了一个非常大的字符串数据(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");
    }
Run Code Online (Sandbox Code Playgroud)

在上面的代码中,它上升到大约100 MB.只有当我执行Api.JetTerm(实例)时,内存才会被释放.

在我真正的问题中,我不得不经常多次插入大量数据行,所以它不会以这种方式对我有效,因为内存最终会被吃掉.

有人可以帮我这个吗?

**即使我提交了交易,为什么esent会保留内存?

我怀疑它是内存中的撤消内容,如果存在,如何将其关闭?我不需要撤消.**

谢谢

PS:我在32位和64位Windows中尝试过这种test()方法,两者都有相同的内存问题.

Mar*_*hma 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似乎可以解决内存使用量增加的问题.