MongoDB / C # Драйвер и проблема с памятью - PullRequest
7 голосов
/ 02 августа 2011

Я использую MongoDB 1.8.2 (Debian) и mongo-csharp-driver 1.1.0.4184 (IIS 7.5 / .Net 4.0 x64).

Несколько элементов вставляются каждую секунду в существующую коллекцию с~ 3 000 000 объектов (~ 1,9 ГБ).
Объем памяти WebServer увеличивается на ~ 1 МБ после каждой вставки ->, что очень быстро приводит к использованию> 2 ГБ памяти.
Память больше не освобождается, и только приложениеУтилизация пула может освободить память.

Есть идеи?

MongoServer server = MongoServer.Create(mongoDBConnectionString);
MongoDatabase database = server.GetDatabase(dbName);                

MongoCollection<Result> resultCollection = database.GetCollection<Result>("Result");
resultCollection.Insert(result);

результат выглядит как

private class Result
{
    public ObjectId _id { get; set; }            
    public DateTime Timestamp { get; set; }
    public int Location { get; set; }            
    public string Content { get; set; }
}

ОБНОВЛЕНИЕ:

Моя проблема не в вставке, а в выборе - извините, странная кодовая база дляисследовать; -)

Я воспроизвел его с этим примером Код:

Console.WriteLine("Start - " + GC.GetTotalMemory(false).ToString("#,###,##0") + " Bytes");

for (int i = 0; i < 10; i++)
{
    MongoServer server = MongoServer.Create(mongoDBConnectionString);
    MongoDatabase database = server.GetDatabase(dbName);

    MongoCollection<Result> resultCollection = database.GetCollection<Result>("Result");
    var query = Query.And ( Query.EQ("Location", 1), Query.GTE("Timestamp", DateTime.Now.AddDays(-90)) );

    MongoCursor<Result> cursor = resultCollection.FindAs<Result>(query);

    foreach (Result result in cursor)
    {
        // NOOP
    }

    Console.WriteLine(i + " - " + GC.GetTotalMemory(false).ToString("#,###,##0") + " Bytes");
}

Вывод из .Net 4.0 Консольное приложение с 10.000 результатов в курсоре:

Start - 193.060 Bytes
0 - 12.736.588 Bytes
1 - 24.331.600 Bytes
2 - 16.180.484 Bytes
3 - 13.223.036 Bytes
4 - 30.974.892 Bytes
5 - 13.335.236 Bytes
6 - 13.439.448 Bytes
7 - 13.942.436 Bytes
8 - 14.026.108 Bytes
9 - 14.113.352 Bytes

Вывод из .Net 4.0 веб-приложения с теми же 10.000 приводит к появлению курсора:

Start - 5.258.376 Bytes 
0 - 20.677.816 Bytes
1 - 29.893.880 Bytes
2 - 43.783.016 Bytes
3 - 20.921.280 Bytes
4 - 34.814.088 Bytes
5 - 48.698.704 Bytes
6 - 62.576.480 Bytes
7 - 76.453.728 Bytes
8 - 90.347.360 Bytes
9 - 104.232.800 Bytes

РЕЗУЛЬТАТ:

Об ошибке сообщили 10gen, и они исправят ее в версии> = 1.4 (в настоящее время они работают на 1.2) !!!

1 Ответ

3 голосов
/ 02 августа 2011

Согласно документации вам следует создать один экземпляр MongoServer для одного сервера, к которому вы подключились:

Класс MongoServer

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

Так что вам нужен только один экземпляр MongoServer. Это должно решить проблему утечек памяти.

Я предлагаю использовать внедрение зависимостей ( unity , карта структуры , ..), чтобы зарегистрировать экземпляр MongoServer в контейнере как синглетон или просто использовать классический singletone шаблон для MongoServer. Если вы новичок в внедрении зависимостей, вы можете взглянуть на Martin Fowler article .

Обновление:

Возможно, проблема не в драйвере mongodb c #. Я сделал следующее тестирование:

w7, iis 7.5, тот же драйвер c #, тот же mongodb:

for (int i = 0; i < 3000000; i++)
{
   MongoServer server = MongoServer.Create("mongodb://localhost:27020");
   MongoDatabase database = server.GetDatabase("mpower_read");

   MongoCollection<Result> resultCollection = 
                              database.GetCollection<Result>("results");

   resultCollection.Insert(new Result()
   {
     _id = ObjectId.GenerateNewId(),
     Content = i.ToString(),
     Location = i,
     Timestamp = DateTime.Now
   });
}

Я даже запускал этот тест 3 раза, а сервер вообще не кушал память. Итак ...

...