C
C#•2y ago
aswinfrancis

Need help finding memory leak [Answered]

We have a solution with a mix of VB and C# projects. Most of them in VB. We have a logger factory written in C# that is used by VB code to write log using nlog. When running load test I see that it consumes close to 4GB of memory. I used debug diag and mempory profiler and they all recommend an event handler leak as seen in the screenshot The code flow for one of the call stack is as seen below:
Public Class ScreenText Implements System.Collections.IEnumerable
Private logger As ILogger = New LoggerFactory().CreateLoggerNlog("Admin_" + DateTime.Now.ToString("yyyyMMdd"))
...
...
Public Class ScreenText Implements System.Collections.IEnumerable
Private logger As ILogger = New LoggerFactory().CreateLoggerNlog("Admin_" + DateTime.Now.ToString("yyyyMMdd"))
...
...
----------------
public class LoggerFactory : ILoggerFactory
{
public ILogger CreateLoggerNlog(string categoryName)
{
this.AddNLog(new NLog.LogFactory());
Logger logger;
lock (_sync)
{
if (!_loggers.TryGetValue(categoryName, out logger))
{
logger = new Logger(this, categoryName);
_loggers[categoryName] = logger;
}
}
return logger;
}
.....
}
public class LoggerFactory : ILoggerFactory
{
public ILogger CreateLoggerNlog(string categoryName)
{
this.AddNLog(new NLog.LogFactory());
Logger logger;
lock (_sync)
{
if (!_loggers.TryGetValue(categoryName, out logger))
{
logger = new Logger(this, categoryName);
_loggers[categoryName] = logger;
}
}
return logger;
}
.....
}
-----------
public static class NLogLoggerFactoryExtensions
{
public static ILoggerFactory AddNLog(
this ILoggerFactory factory,
global::NLog.LogFactory logFactory)
{
factory.AddProvider(new NLogLoggerProvider(logFactory));
return factory;
}
}
public static class NLogLoggerFactoryExtensions
{
public static ILoggerFactory AddNLog(
this ILoggerFactory factory,
global::NLog.LogFactory logFactory)
{
factory.AddProvider(new NLogLoggerProvider(logFactory));
return factory;
}
}
------------
public class NLogLoggerProvider : ILoggerProvider
{
private readonly LogFactory _logFactory;

public NLogLoggerProvider(LogFactory logFactory)
{
_logFactory = logFactory;
}
....
}
public class NLogLoggerProvider : ILoggerProvider
{
private readonly LogFactory _logFactory;

public NLogLoggerProvider(LogFactory logFactory)
{
_logFactory = logFactory;
}
....
}
------------- Looks like if i set logger = Nothing inside ScreenText class' Finalize() method. This issue isnt happening. But I am wondering if there is problem in logger factory approach that is the main reason and why these are showing as event handler leaks?
5 Replies
Dusty
Dusty•2y ago
How many instances of the ScreenText exist at a time? You're creating multiple instances of your LoggerFactory there of which each holds multiple instances of your loggers. Normally you have 1 LoggerFactory instance which provides new loggers
aswinfrancis
aswinfrancis•2y ago
Agreed. After some more analysis after I put this up I found the reason. The original Dev had a dictionary property that was meant to hold logger factories and then only create fresh ones if it wasn't there but the property would be created new every time as it wasn't static. Every time they call New LoggerFactory().CreateLoggerNlog(), a new dictionary property was created which in turn causes new loggerfactory instance to be created
Dusty
Dusty•2y ago
makes sense, glad you found it 😄
Unknown User
Unknown User•2y ago
Message Not Public
Sign In & Join Server To View
Accord
Accord•2y ago
✅ This post has been marked as answered!