ESENT дБ утечки памяти? - PullRequest
       21

ESENT дБ утечки памяти?

5 голосов
/ 17 октября 2011

Я только начал использовать ESENT ManagedInterface (http://managedesent.codeplex.com/). Мне интересно, есть ли у него проблема утечки памяти.

То, что я делаю, довольно просто. Я следовал примеру кода, но я поместил довольно большойстроковые данные (10 КБ +) в каждой строке и в общей сложности 10000 строк.

Использование памяти увеличивается при добавлении большего количества строк. Если я вставлю примерно 100 000 строк, программа израсходует 1 ГБ памяти и умрет.

Вот код.

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 МБ. Только если я делаю Api.JetTerm (экземпляр), память освобождается .

В моей реальной проблеме мне приходится много раз многократно вставлять строки большого количества данных, так что это не будет работать для меня таким образом, как памятьв конечном итоге будет съеден.

Может ли кто-нибудь помочь мне с этим?

** Почему esent хранит память, даже если я совершил транзакцию?

Я подозреваю ееэто отмена вещей внутри, которая хранит память, иесли есть, то как его отключить?Мне не нужно ничего отменять. **

Спасибо

PS: я пробовал этот метод test () как в 32-битной, так и в 64-битной Windows, у обоих одинаковая проблема с памятью.

Ответы [ 2 ]

8 голосов
/ 17 октября 2011

Поможет ли это: 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, похоже, решает проблему с увеличением использования памяти.

4 голосов
/ 21 июня 2012

Извините, я так опоздал на вечеринку ...

Я бы заметил, что это не устраняет утечку памяти, а снижает производительность двигателя.Размер кэша - это кеширование страниц базы данных в памяти таким образом, чтобы вы меньше обращались к диску ... как это делает хорошая база данных.;) Если вы уменьшите это, вам будет не по себе и вам потребуется больше дискового ввода-вывода.

Ядро базы данных достаточно разумно, чтобы отступать, когда видит, что другие люди используют память, поэтому теоретически у вас не должно быть размеракеш, подобный этому, освободит память, если увидит, что другие хотят этого.

Итак, нет, если вы действительно не знаете, что вам нужно это делать, я бы не рекомендовал это.

...