Memory leak in Managed SimConnect SetDataOnSimObject?

Discuss on the SimConnect SDK can be used by programmers to write add-on components for Prepar3D
Post Reply
zillmer
Posts: 14
Joined: Wed Jan 03, 2018 4:57 pm

Memory leak in Managed SimConnect SetDataOnSimObject?

Post by zillmer »

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.
obinder
Posts: 145
Joined: Sun Jun 08, 2014 9:43 am

Re: Memory leak in Managed SimConnect SetDataOnSimObject?

Post by obinder »

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
EllipticCurve
Posts: 152
Joined: Mon Jun 12, 2017 6:14 pm

Re: Memory leak in Managed SimConnect SetDataOnSimObject?

Post by EllipticCurve »

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.
All comments and opinions are my own.
zillmer
Posts: 14
Joined: Wed Jan 03, 2018 4:57 pm

Re: Memory leak in Managed SimConnect SetDataOnSimObject?

Post by zillmer »

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);
}

}
}
}
}
EllipticCurve
Posts: 152
Joined: Mon Jun 12, 2017 6:14 pm

Re: Memory leak in Managed SimConnect SetDataOnSimObject?

Post by EllipticCurve »

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;
All comments and opinions are my own.
zillmer
Posts: 14
Joined: Wed Jan 03, 2018 4:57 pm

Re: Memory leak in Managed SimConnect SetDataOnSimObject?

Post by zillmer »

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.
obinder
Posts: 145
Joined: Sun Jun 08, 2014 9:43 am

Re: Memory leak in Managed SimConnect SetDataOnSimObject?

Post by obinder »

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
zillmer
Posts: 14
Joined: Wed Jan 03, 2018 4:57 pm

Re: Memory leak in Managed SimConnect SetDataOnSimObject?

Post by zillmer »

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.
EllipticCurve
Posts: 152
Joined: Mon Jun 12, 2017 6:14 pm

Re: Memory leak in Managed SimConnect SetDataOnSimObject?

Post by EllipticCurve »

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.
I disagree. C# has a delete keyword.

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.
obinder
Posts: 145
Joined: Sun Jun 08, 2014 9:43 am

Re: Memory leak in Managed SimConnect SetDataOnSimObject?

Post by obinder »

zillmer wrote: Mon Apr 29, 2019 9:10 pm 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.
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
metacraft
Posts: 14
Joined: Thu Feb 16, 2012 10:07 pm

Re: Memory leak in Managed SimConnect SetDataOnSimObject?

Post by metacraft »

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.
Post Reply