Memory leak in Managed SimConnect SetDataOnSimObject?
Memory leak in Managed SimConnect SetDataOnSimObject?
Hi,
I'm trying to get to the bottom of a problem I am having using the managed SimConnect library. I am using this to create new SimObjects in Prepar3d and then send position updates to them using the SetDataOnSimObject function.
My code functions perfectly in that the objects I want are created, they respond to the updated data as I expect, and no exceptions are thrown. However, the memory usage of the app increases with each call to the SetDataOnSimObject function. The consequence of this is that over time the memory consumed by my app increases to a point where the app simply crashes to desktop. I have demonstrated that the app has no memory usage issue if I comment out the SetDataOnSimObject call. I have checked and double checked the Data Structure I have created to ensure it is marshalled correctly, and I can do equivalent GetDataOnSimObject on the same structure with no memory impact whatsoever.
I first detected the problem in a more complex application with multi-threading, but have since created a simplified app that only creates the simobjects and then sends the updates, and I experience the same behaviour.
Has any one else experienced this or have any suggestions?
Regards
Simon.
I'm trying to get to the bottom of a problem I am having using the managed SimConnect library. I am using this to create new SimObjects in Prepar3d and then send position updates to them using the SetDataOnSimObject function.
My code functions perfectly in that the objects I want are created, they respond to the updated data as I expect, and no exceptions are thrown. However, the memory usage of the app increases with each call to the SetDataOnSimObject function. The consequence of this is that over time the memory consumed by my app increases to a point where the app simply crashes to desktop. I have demonstrated that the app has no memory usage issue if I comment out the SetDataOnSimObject call. I have checked and double checked the Data Structure I have created to ensure it is marshalled correctly, and I can do equivalent GetDataOnSimObject on the same structure with no memory impact whatsoever.
I first detected the problem in a more complex application with multi-threading, but have since created a simplified app that only creates the simobjects and then sends the updates, and I experience the same behaviour.
Has any one else experienced this or have any suggestions?
Regards
Simon.
Re: Memory leak in Managed SimConnect SetDataOnSimObject?
Hello Simon,
I am using that SimConnect method extensively in many of my apps (which are all managed code). I never experienced any memory issues, and neither did customers (AFAIK). Updates happen with every frame mostly, so if there was a problem, memory consumption would explode quickly.
I am using global variables mostly, overwriting their values before they are sent to the sim, but there is the occasional local variable too, with no ill effects.
Best regards
Oliver Binder
Lorby-SI
I am using that SimConnect method extensively in many of my apps (which are all managed code). I never experienced any memory issues, and neither did customers (AFAIK). Updates happen with every frame mostly, so if there was a problem, memory consumption would explode quickly.
I am using global variables mostly, overwriting their values before they are sent to the sim, but there is the occasional local variable too, with no ill effects.
Best regards
Oliver Binder
Lorby-SI
-
- Posts: 152
- Joined: Mon Jun 12, 2017 6:14 pm
Re: Memory leak in Managed SimConnect SetDataOnSimObject?
Hi,
Are you using Reflection?
IIRC it is YOUR duty to clean up memory when the call returns. Can you post how you are handling the data?
Be sure that you are de-allocating the object before you return. If you just keep allocating and not freeing, the Garbage Collector can sometimes fail and so an object that appears to be free is not, and so doesn't get removed.
The safest way is to allocate an object, then before you exit:
// free object here
// more stuff...
object = null;
GC.Collect();
GC.WaitForPendingFinalizers();
GC.Collect();
// exit function
If it still leaks, then the problem is the object is not getting released.
Are you using Reflection?
IIRC it is YOUR duty to clean up memory when the call returns. Can you post how you are handling the data?
Be sure that you are de-allocating the object before you return. If you just keep allocating and not freeing, the Garbage Collector can sometimes fail and so an object that appears to be free is not, and so doesn't get removed.
The safest way is to allocate an object, then before you exit:
// free object here
// more stuff...
object = null;
GC.Collect();
GC.WaitForPendingFinalizers();
GC.Collect();
// exit function
If it still leaks, then the problem is the object is not getting released.
All comments and opinions are my own.
Re: Memory leak in Managed SimConnect SetDataOnSimObject?
Oliver,
Thanks. A rapid explosion in memory use is exactly what I experience in my app.
I have created a very simple windows forms app for testing from scratch. I've pasted the code below. Running this code I get a continuous steady increase in memory usage by the app. This is about as simple as it gets so I'm not sure what's going on.
Regards
Simon.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Runtime.InteropServices;
using LockheedMartin.Prepar3D.SimConnect;
namespace SImObjectDataTest
{
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)]
public struct SimObjectState
{
public double Heading;
}
public enum StructureType
{
SimObjectData
}
enum CreateID
{
CreateAircraft=1
}
public partial class Form1 : Form
{
private bool P3DConnected=false;
private double Heading = 0;
const int WmUserSimconnect = 0x0402;
private bool UpdateObjects = false;
List<uint> _objectlist=new List<uint>();
private SimConnect simconnect;
public Form1()
{
InitializeComponent();
}
protected override void DefWndProc(ref Message m)
{
if (m.Msg == WmUserSimconnect)
{
simconnect.ReceiveMessage();
}
else
{
base.DefWndProc(ref m);
}
}
private void connectButton_Click(object sender, EventArgs e)
{
if (!P3DConnected)
{
simconnect = new SimConnect("TrafficSync", Handle, WmUserSimconnect, null, 0);
simconnect.OnRecvOpen += Simconnect_OnRecvOpen;
simconnect.OnRecvAssignedObjectId += Simconnect_OnRecvAssignedObjectId;
}
}
private void Simconnect_OnRecvAssignedObjectId(SimConnect sender, SIMCONNECT_RECV_ASSIGNED_OBJECT_ID data)
{
// Just add the id to a list.
_objectlist.Add(data.dwObjectID);
}
private void Simconnect_OnRecvOpen(SimConnect sender, SIMCONNECT_RECV_OPEN data)
{
P3DConnected = true;
simconnect.AddToDataDefinition(StructureType.SimObjectData, "PLANE HEADING DEGREES TRUE", "degrees", SIMCONNECT_DATATYPE.FLOAT64, 0.0f, SimConnect.SIMCONNECT_UNUSED);
simconnect.RegisterDataDefineStruct<SimObjectState>(StructureType.SimObjectData);
}
private void createObjects_Click(object sender, EventArgs e)
{
// Create the sim objects
if (P3DConnected)
{
SIMCONNECT_DATA_INITPOSITION position = new SIMCONNECT_DATA_INITPOSITION();
position.Airspeed = 0;
position.OnGround = 1;
position.Pitch = 0;
position.Bank = 0;
position.Heading = 0;
position.Latitude = 48.34066667;
position.Longitude = 11.75183333;
position.Altitude = 1496.1;
for (int iCtr = 1; iCtr < 100; iCtr++)
{
position.Latitude += (float) iCtr / 36000;
simconnect.AICreateNonATCAircraft("FAIB Airbus A320 Roll-Out Colors CFM", "dfg", position,
CreateID.CreateAircraft);
}
}
}
private void updateSimObjects_Click(object sender, EventArgs e)
{
UpdateObjects = true;
timer1.Enabled = true;
timer1.Start();
}
private void timer1_Tick(object sender, EventArgs e)
{
if (UpdateObjects)
{
// So send a simobject update to the sim.
SimObjectState state = new SimObjectState();
Heading++;
if (Heading > 360)
Heading = 0;
state.Heading = Heading;
foreach (uint a in _objectlist)
{
simconnect.SetDataOnSimObject(StructureType.SimObjectData,a,0,state);
}
}
}
}
}
Thanks. A rapid explosion in memory use is exactly what I experience in my app.
I have created a very simple windows forms app for testing from scratch. I've pasted the code below. Running this code I get a continuous steady increase in memory usage by the app. This is about as simple as it gets so I'm not sure what's going on.
Regards
Simon.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Runtime.InteropServices;
using LockheedMartin.Prepar3D.SimConnect;
namespace SImObjectDataTest
{
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)]
public struct SimObjectState
{
public double Heading;
}
public enum StructureType
{
SimObjectData
}
enum CreateID
{
CreateAircraft=1
}
public partial class Form1 : Form
{
private bool P3DConnected=false;
private double Heading = 0;
const int WmUserSimconnect = 0x0402;
private bool UpdateObjects = false;
List<uint> _objectlist=new List<uint>();
private SimConnect simconnect;
public Form1()
{
InitializeComponent();
}
protected override void DefWndProc(ref Message m)
{
if (m.Msg == WmUserSimconnect)
{
simconnect.ReceiveMessage();
}
else
{
base.DefWndProc(ref m);
}
}
private void connectButton_Click(object sender, EventArgs e)
{
if (!P3DConnected)
{
simconnect = new SimConnect("TrafficSync", Handle, WmUserSimconnect, null, 0);
simconnect.OnRecvOpen += Simconnect_OnRecvOpen;
simconnect.OnRecvAssignedObjectId += Simconnect_OnRecvAssignedObjectId;
}
}
private void Simconnect_OnRecvAssignedObjectId(SimConnect sender, SIMCONNECT_RECV_ASSIGNED_OBJECT_ID data)
{
// Just add the id to a list.
_objectlist.Add(data.dwObjectID);
}
private void Simconnect_OnRecvOpen(SimConnect sender, SIMCONNECT_RECV_OPEN data)
{
P3DConnected = true;
simconnect.AddToDataDefinition(StructureType.SimObjectData, "PLANE HEADING DEGREES TRUE", "degrees", SIMCONNECT_DATATYPE.FLOAT64, 0.0f, SimConnect.SIMCONNECT_UNUSED);
simconnect.RegisterDataDefineStruct<SimObjectState>(StructureType.SimObjectData);
}
private void createObjects_Click(object sender, EventArgs e)
{
// Create the sim objects
if (P3DConnected)
{
SIMCONNECT_DATA_INITPOSITION position = new SIMCONNECT_DATA_INITPOSITION();
position.Airspeed = 0;
position.OnGround = 1;
position.Pitch = 0;
position.Bank = 0;
position.Heading = 0;
position.Latitude = 48.34066667;
position.Longitude = 11.75183333;
position.Altitude = 1496.1;
for (int iCtr = 1; iCtr < 100; iCtr++)
{
position.Latitude += (float) iCtr / 36000;
simconnect.AICreateNonATCAircraft("FAIB Airbus A320 Roll-Out Colors CFM", "dfg", position,
CreateID.CreateAircraft);
}
}
}
private void updateSimObjects_Click(object sender, EventArgs e)
{
UpdateObjects = true;
timer1.Enabled = true;
timer1.Start();
}
private void timer1_Tick(object sender, EventArgs e)
{
if (UpdateObjects)
{
// So send a simobject update to the sim.
SimObjectState state = new SimObjectState();
Heading++;
if (Heading > 360)
Heading = 0;
state.Heading = Heading;
foreach (uint a in _objectlist)
{
simconnect.SetDataOnSimObject(StructureType.SimObjectData,a,0,state);
}
}
}
}
}
-
- Posts: 152
- Joined: Mon Jun 12, 2017 6:14 pm
Re: Memory leak in Managed SimConnect SetDataOnSimObject?
private void timer1_Tick(object sender, EventArgs e)
{
if (UpdateObjects)
{
// So send a simobject update to the sim.
SimObjectState state = new SimObjectState(); // <<<<<<<<<<< THIS IS YOUR PROBLEM HERE!
Heading++;
if (Heading > 360)
Heading = 0;
state.Heading = Heading;
foreach (uint a in _objectlist)
{
simconnect.SetDataOnSimObject(StructureType.SimObjectData,a,0,state);
}
}
}
=============================
At the end of this function, add:
delete SimObjectState();
SimObjectState = null;
{
if (UpdateObjects)
{
// So send a simobject update to the sim.
SimObjectState state = new SimObjectState(); // <<<<<<<<<<< THIS IS YOUR PROBLEM HERE!
Heading++;
if (Heading > 360)
Heading = 0;
state.Heading = Heading;
foreach (uint a in _objectlist)
{
simconnect.SetDataOnSimObject(StructureType.SimObjectData,a,0,state);
}
}
}
=============================
At the end of this function, add:
delete SimObjectState();
SimObjectState = null;
All comments and opinions are my own.
Re: Memory leak in Managed SimConnect SetDataOnSimObject?
Thanks Elliptic, but this is C# code. You don't need to delete objects in the same way as is done in C++. The code you posted isn't recognised by C# in any event.
I've done some performance profiling using Visual Studio and all I can see from that is that the additional memory that is being used is being allocated by the SimConnect.dll. In the example code above it looks like is allocating an additional 8 bytes on each call to SetDataOnSimObject.
I've done some performance profiling using Visual Studio and all I can see from that is that the additional memory that is being used is being allocated by the SimConnect.dll. In the example code above it looks like is allocating an additional 8 bytes on each call to SetDataOnSimObject.
Re: Memory leak in Managed SimConnect SetDataOnSimObject?
Hello Simon,
I am running your program right now on P3D 4.4 (I copy&pasted your code and dropped the buttons on the form). The process starts out at 24 MB, upon creation of the 100 aircraft at EDDM (I am using the FLAI Airbus A340) and after starting the SetDataOnSimobject loop that makes them turn, memory consumption goes up to 33 MB quickly, then slows down - but it is still rising very slowly - about 1 MB every 2 minutes. So 8 bytes on top per operation sounds about right. I have doublechecked with other apps, and the memory increasing slowly but steadily is present everywhere. But I don't think that it is limited to the SetDataOnSimobject, this seems to be a general issue with SimConnect, with other methods too. The heap size and number of objects remain the same though. It is getting late, I will do more tests tomorrow, see how this works in the previous SimConnect versions.
How quickly does memory consumption go up when you are observing it?
Best regards
Oliver Binder
Lorby-SI
I am running your program right now on P3D 4.4 (I copy&pasted your code and dropped the buttons on the form). The process starts out at 24 MB, upon creation of the 100 aircraft at EDDM (I am using the FLAI Airbus A340) and after starting the SetDataOnSimobject loop that makes them turn, memory consumption goes up to 33 MB quickly, then slows down - but it is still rising very slowly - about 1 MB every 2 minutes. So 8 bytes on top per operation sounds about right. I have doublechecked with other apps, and the memory increasing slowly but steadily is present everywhere. But I don't think that it is limited to the SetDataOnSimobject, this seems to be a general issue with SimConnect, with other methods too. The heap size and number of objects remain the same though. It is getting late, I will do more tests tomorrow, see how this works in the previous SimConnect versions.
How quickly does memory consumption go up when you are observing it?
Best regards
Oliver Binder
Lorby-SI
Re: Memory leak in Managed SimConnect SetDataOnSimObject?
Oliver,
I get the same rate as you are seeing with the code I pasted, but if I add additional data to the structure it seems to scale proportionately, so the more data is included in the SetData request the more memory builds up.
Simon.
I get the same rate as you are seeing with the code I pasted, but if I add additional data to the structure it seems to scale proportionately, so the more data is included in the SetData request the more memory builds up.
Simon.
-
- Posts: 152
- Joined: Mon Jun 12, 2017 6:14 pm
Re: Memory leak in Managed SimConnect SetDataOnSimObject?
I disagree. C# has a delete keyword.zillmer wrote: ↑Mon Apr 29, 2019 5:29 pm Thanks Elliptic, but this is C# code. You don't need to delete objects in the same way as is done in C++. The code you posted isn't recognised by C# in any event.
I've done some performance profiling using Visual Studio and all I can see from that is that the additional memory that is being used is being allocated by the SimConnect.dll. In the example code above it looks like is allocating an additional 8 bytes on each call to SetDataOnSimObject.
Yes, there is scoping, and when it drops out of scope it *should* free the resources, but actually this is not guaranteed.
All comments and opinions are my own.
Re: Memory leak in Managed SimConnect SetDataOnSimObject?
Hello Simon,
I have added a memory monitor in code, so it controls itself even when run outside of VS. And I have tested it with FSX:SE and native SimConnect. The results are pretty much alike, on average I get about 1 MByte of additional process memory per minute. It doesn't really depend on what I do in SimConnect though. This looks like memory address pointers being created but never erased again, but it is hard to tell of course.
Definitely something that Lockheed should look into IMHO.
Although I can't get it to OOM like you are describing in the OP. Besides, with today's memory sizes, even an increase of half a gigabyte per hour would probably go unnoticed by most. And has been for the last 10+ years apparently, although it makes me wonder why the notoriously memory shy FSXers didn't find this. Maybe it only happens with external programs and not with internal DLLs or gauges?
Best regards
Oliver Binder
Lorby-SI
Re: Memory leak in Managed SimConnect SetDataOnSimObject?
Did anyone find a fix/workaround for this? I'm seeing the same thing in an app that calls SetDataOnSimObject once per visual frame for each aircraft object. The higher my framerate, and the more aircraft there are nearby, the faster the memory leak accumulates. I have tried deleting the struct, setting it to null, and forcing a GC run. It appears that the simconnect client DLL is hanging onto the memory.