2

We have a webAPI in our project which is very simple but it does not release the memory after execution and every time it is executed, it increases the used memory.

I was using webAPI 2.0 and MongoDB as back end server.

public class LogsController:ApiController
{
    BsonDocument __docs;
    IMongoDatabase __db;
    IMongoCollection<BsonDocument> __docsColl;
    [Route("api/Logs")]
    public async Task<int> Post(RequestData logs)
    {
        if (logs.Token == "I")
        {
            __db = new MongoClient(new MongoClientSettings
            {
                Server = new MongoServerAddress("serverIP", 27017),
                Credentials = new[] { MongoCredential.CreateCredential("database", "user name", "password") }
            }).GetDatabase("connect_database");

            __docs = new BsonDocument()
            {
                { "Customer",logs.Customer}
            };
            __docsColl = __db.GetCollection<BsonDocument>("InsertData");
            await __docsColl.InsertOneAsync(__docs);
        }
        logs = null;
        return 1;
    }

    protected override void Dispose(bool disposing)
    {
        __docs = null;
        __db = null;
        __docsColl = null;
        GC.SuppressFinalize(true);
        base.Dispose(disposing);
    }

}

I have tried all possible solutions I found, but so far no luck.

Ebg Test
  • 91
  • 1
  • 11
  • 1
    `it is not release memory` `every time it will increase the memory` how did you arrive to these conclusions? Is there a log or execution result you can post? – cosh Feb 01 '18 at 14:06
  • 1
    You do not call the "Dispose" method anywhere. – TanguyB Feb 01 '18 at 14:07
  • 1
    Do you have a specific reason for declaring 3 global variables? Are they used anywhere in this class, outside of the `Post()` method? – Bernd Linde Feb 01 '18 at 14:10
  • As webAPI implement IDisposable so it will automatic call after webAPI response that i have check using debug and it will call Dispose method. – Ebg Test Feb 01 '18 at 14:13
  • @Bernd Linde no i have declare this only for the set null after webAPI response. – Ebg Test Feb 01 '18 at 14:14
  • 1
    remove Dispose(), Move properties into the Post(). Remove "...= null", report result – alerya Feb 01 '18 at 14:15
  • @isaac i have deploy this in server and then call the webAPI from postman and check that memory only increase every time after webAPI cal – Ebg Test Feb 01 '18 at 14:15
  • Have you tried to only have local variables inside the `Post()` method and see if that releases the objects correctly? You can always use a try..finally before the `return 1` to set those variables to null if it is really needed. – Bernd Linde Feb 01 '18 at 14:15
  • @alerya i will try and update you about the result. Thanks for the quick answer. – Ebg Test Feb 01 '18 at 14:17
  • @BerndLinde i will try and update you about the result. Thanks for the quick answer. – Ebg Test Feb 01 '18 at 14:18
  • https://stackoverflow.com/a/32703627 – Eldho Feb 01 '18 at 15:04
  • You dont need to create a instance for mongo. Its thread safe you can create a global instance of mongo & share among multiple threads. You could use your ioc container or app start to register a singleton instance for you. – Eldho Feb 01 '18 at 15:07
  • How do you profile memory leak ? – Eldho Feb 01 '18 at 15:08
  • @Eldho can you please provide some basic code example for the better understanding. And for profile memory leak i have use the tools .NET Memory profile. – Ebg Test Feb 02 '18 at 05:49
  • I don't have exact code base for your requirements, I don't have VS now. please try http://www.qappdesign.com/using-mongodb-with-net-core-webapi/ – Eldho Feb 02 '18 at 06:34
  • After the long time spend into this found that Post parameter (RequestData) of webAPI use this memory and not clear because it's have a string properties. – Ebg Test Feb 02 '18 at 11:53

2 Answers2

6

When webAPI call with the post parameters then it will deserialize into the class which is we are use as the parameters.

Further checking found that when class content the string datatype then it will use the memory and not release at a time after response return from webAPI.

If you really required memory then you must need to override Dispose method of ApiController.

Code block should be:

protected override void Dispose(bool disposing)
        {
            GC.Collect(GC.MaxGeneration, GCCollectionMode.Forced);
            base.Dispose(disposing);
        }

GC.Collect is not recommended method but when your posting large amount of data in parameter you must need to use this for free memory quickly.

Ebg Test
  • 91
  • 1
  • 11
0

Initialize MongoClient in the constructor of the LogsController and not in the Post method.

Michael Puckett II
  • 6,586
  • 5
  • 26
  • 46
  • IMongoClient is not IDisposable. So it Clear itself correctly. If it has memory leaks... that real problem for this libraries creators. – alerya Feb 02 '18 at 07:37
  • 1
    @alerya That's interesting... Well if there's a memory leak it's almost certainly related to one of the Mongo objects or BsonDocuments being creating. IMongoDatabase may not be disposable but is MongoClient? Maybe the interface needs updating or something. Strange indeed. Marking up the question as I'm curious. – Michael Puckett II Feb 02 '18 at 19:44
  • 3
    @MichaelPuckettII found the issue that when we will post that data to the webAPI as Application/JSON format it will used the memory and then it will not clear the memory for that post parameters. There was nothing wrong inside the MongoClient as it was tread safe. – Ebg Test Feb 03 '18 at 11:09
  • @EbgTest Awesome, thanks for sharing. Can you post the full answer as an answer in the thread? You can mark it as answered after 24 hours. – Michael Puckett II Feb 03 '18 at 17:36