Elvas Tower: memory using monogame or - Elvas Tower

Jump to content

  • 8 Pages +
  • « First
  • 2
  • 3
  • 4
  • 5
  • 6
  • Last »
  • You cannot start a new topic
  • You cannot reply to this topic

memory using monogame or Rate Topic: -----

#31 User is offline   Csantucci 

  • Member, Board of Directors
  • Group: Status: Elite Member
  • Posts: 7,015
  • Joined: 31-December 11
  • Gender:Male
  • Country:

Posted 13 December 2021 - 01:05 AM

 Serana, on 11 December 2021 - 01:29 PM, said:

What has been troubling me was that, when I used a memory profiling tool (dotMemory), after creating a snapshot, the memory occupation dropped suddenly.
Since there is a lot of garbage collections going on... perhaps we are throwing away too many variables and the GC is not quick enough to delete them all (that's what is called GC pressure).
That's probably why when the program is paused to create the snapshot, the memory occupation drops suddenly: because the GC had the time to delete the unused variables.

This is something I noticed too, see here
http://www.elvastowe...post__p__277886

#32 User is offline   Serana 

  • Conductor
  • Group: Status: Contributing Member
  • Posts: 489
  • Joined: 21-February 13
  • Gender:Male
  • Location:St Cyr l'Ecole (France)
  • Simulator:Open Rails
  • Country:

Posted 13 December 2021 - 10:52 AM

Ok, to sum up what we know currently, the plan is to:
1) Reduce the GC pressure as much as possible:
- We have to avoid throwing away variables and reuse them as much as possible.

2) Be careful about string usage:
- Each time you modify a string, you are creating a new object because strings are immutable.
- When creating strings with multiple operations, StringBuilder must be used.

3) Try to find leaks in the unmanaged momory:
- Mainly GPU RAM and when we are using libraries that were coded in C/C++

#33 User is offline   James Ross 

  • Open Rails Developer
  • Group: Status: Elite Member
  • Posts: 5,492
  • Joined: 30-June 10
  • Gender:Not Telling
  • Simulator:Open Rails
  • Country:

Posted 13 December 2021 - 01:15 PM

 Serana, on 08 December 2021 - 02:11 PM, said:

GPU memory is generally used by textures. Do you think this memory "leak" is due to textures remaining in VRAM?

Textures, vertex buffers, and index buffers come to mind but there might be others.

 Serana, on 08 December 2021 - 02:11 PM, said:

On StackOverflow, I have read that textures loaded manually are not removed from VRAM automatically if we don't use the content manager of XNA/MonoGame.
We have to call the Dispose function manually and I don't think we are currently calling this function. (See https://stackoverflow.com/a/48777516)

It would be quite surprising to me if we had to call "Dispose()" ourselves, since textures (and other graphics) device objects are all "IDisposable" and have what appears to be a correctly-implemented C# destructor.

I can see three possible reasons why we might be leaking graphical resources:

  • Open Rails is incorrectly keeping a reference to the object somewhere
  • MonoGame is incorrectly keeping a reference to the object somewhere
  • The runtime/CLR is unable to keep up with the rate at which "IDisposable" objects are being created/let go


 Serana, on 13 December 2021 - 10:52 AM, said:

1) Reduce the GC pressure as much as possible:
- We have to avoid throwing away variables and reuse them as much as possible.

The HUD DEBUG page includes a display of how much managed memory is allocated per frame, and we should always be trying to minimise this, but I do not want the code to become unreadable either. :)

 Serana, on 13 December 2021 - 10:52 AM, said:

2) Be careful about string usage:
- Each time you modify a string, you are creating a new object because strings are immutable.
- When creating strings with multiple operations, StringBuilder must be used.

Strings could be a problem, but it probably makes more sense to profile what's being allocated before trying to target anything.

 Serana, on 13 December 2021 - 10:52 AM, said:

3) Try to find leaks in the unmanaged momory:
- Mainly GPU RAM and when we are using libraries that were coded in C/C++

For me, the most important thing to figure out here is why the textures are not being cleaned up automatically, because they should be - and they have in the past. For example, there's no need to start a war on GC garbage if the cause is Open Rails or MonoGame keeping unexpected extra references to the textures. :)


One thing that this thread and another recent memory usage thread have shown, is that there can be significant confusion over memory measurements and what they are actually measuring. I am therefore working on an update to the memory reporting in the HUD DEBUG screen that will include:

  • DRAM - private, working set, and virtual breakdown
  • VRAM - dedicated, shared, and committed breakdown

This will add a lot of new measurements, reducing the need for 3rd party tools (this will be the first time we can measure VRAM usage) and - as a result - reducing the possibility for confusion when comparing between people.

#34 User is offline   Eldorado.Railroad 

  • Foreman Of Engines
  • Group: Status: Contributing Member
  • Posts: 983
  • Joined: 31-May 10
  • Gender:Male
  • Country:

Posted 13 December 2021 - 04:02 PM

 James Ross, on 13 December 2021 - 01:15 PM, said:

It would be quite surprising to me if we had to call "Dispose()" ourselves, since textures (and other graphics) device objects are all "IDisposable" and have what appears to be a correctly-implemented C# destructor.

I can see three possible reasons why we might be leaking graphical resources:

  • Open Rails is incorrectly keeping a reference to the object somewhere
  • MonoGame is incorrectly keeping a reference to the object somewhere
  • The runtime/CLR is unable to keep up with the rate at which "IDisposable" objects are being created/let go

4. Loading and GC are NOT synchronous, and mutually exclusive.


As an experiment turn GC off, completely and see what happens. If you can keep track of objects created on the heap, you should be able to see if duplicates are being created. The IDE debugger should be able to show you that. In practice, as in runtime user experience, that is what I "see",ie duplication, and way MORE!


To really test a fix you are going to have to rely on stress testing this, which means many GB of data being loaded and "hopefully unloaded" over a long period of time. Some of us have those resources on hand. In the past, software development I had worked in "never had the time" for testing! Inevitably things "get broken" when a small data set is being used for testing. I voiced that lack of proper memory management in the previous XNA versions of OR, with proof. Eventually and secretly it was fixed, without acknowledging the person or people who detected it. If anything was learned from that experience, avoiding the issue does not solve a problem. So I am glad that there is some candor here! Yes, we have a problem here.

Always willing to help,

Steve

#35 User is offline   gpz 

  • Superintendant
  • Group: Status: Elite Member
  • Posts: 1,772
  • Joined: 27-October 12
  • Gender:Male
  • Location:Budapest
  • Simulator:OpenRails
  • Country:

Posted 14 December 2021 - 01:09 AM

 James Ross, on 13 December 2021 - 01:15 PM, said:

It would be quite surprising to me if we had to call "Dispose()" ourselves, since textures (and other graphics) device objects are all "IDisposable" and have what appears to be a correctly-implemented C# destructor.

Are you sure about this? To my past understanding, Dispose() is called automatically only if the IDisposable is created within a using() block, which is not the case in our various *Manager()-s, because we store them for later use. To my understanding for such IDisposable classes it is not enough to just release their references, Dispose() or Close() must be called explicitly.

#36 User is offline   James Ross 

  • Open Rails Developer
  • Group: Status: Elite Member
  • Posts: 5,492
  • Joined: 30-June 10
  • Gender:Not Telling
  • Simulator:Open Rails
  • Country:

Posted 14 December 2021 - 01:39 PM

 gpz, on 14 December 2021 - 01:09 AM, said:

Are you sure about this? To my past understanding, Dispose() is called automatically only if the IDisposable is created within a using() block, which is not the case in our various *Manager()-s, because we store them for later use. To my understanding for such IDisposable classes it is not enough to just release their references, Dispose() or Close() must be called explicitly.

You are correctly when the class does not also implement the destructor/finaliser part of Implement the dispose pattern (second code sample), which MonoGame does, as best I can tell.

#37 User is offline   gpz 

  • Superintendant
  • Group: Status: Elite Member
  • Posts: 1,772
  • Joined: 27-October 12
  • Gender:Male
  • Location:Budapest
  • Simulator:OpenRails
  • Country:

Posted 15 December 2021 - 02:42 AM

Ah, thanks, I wasn't aware of that either. However the overview calls the finalizer a "safeguard" when the Dispose() is not called for some reason:

Quote

Consumers of your type can then call your IDisposable.Dispose implementation directly to free memory used by unmanaged resources. When you properly implement a Dispose method, either your safe handle's Finalize method or your own override of the Object.Finalize method becomes a safeguard to clean up resources in the event that the Dispose method is not called.
With the amendment, that:

Quote

In C#, you implement a finalization by providing a finalizer, not by overriding Object.Finalize.

So it yet could be a good idea to call the Dispose() explicitly, maybe.

#38 User is offline   James Ross 

  • Open Rails Developer
  • Group: Status: Elite Member
  • Posts: 5,492
  • Joined: 30-June 10
  • Gender:Not Telling
  • Simulator:Open Rails
  • Country:

Posted 15 December 2021 - 09:55 AM

 gpz, on 15 December 2021 - 02:42 AM, said:

So it yet could be a good idea to call the Dispose() explicitly, maybe.

Yes, even though it shouldn't be necessary, explicitly calling "Dispose()" is a good idea when we're done with graphical resources like textures.

#39 User is offline   James Ross 

  • Open Rails Developer
  • Group: Status: Elite Member
  • Posts: 5,492
  • Joined: 30-June 10
  • Gender:Not Telling
  • Simulator:Open Rails
  • Country:

Posted 15 December 2021 - 09:56 AM

 gpz, on 15 December 2021 - 02:42 AM, said:

So it yet could be a good idea to call the Dispose() explicitly, maybe.

I would also like to add that, if this problem affects 1.4, we should base the code to fix it off the "release/1.4" branch, so that we can create 1.4.1 with the fix if necessary.

#40 User is offline   Genma Saotome 

  • Owner Emeritus and Admin
  • PipPipPipPipPipPipPipPipPipPipPipPipPip
  • Group: ET Admin
  • Posts: 15,360
  • Joined: 11-January 04
  • Gender:Male
  • Location:United States
  • Simulator:Open Rails
  • Country:

Posted 15 December 2021 - 01:40 PM

 Eldorado.Railroad, on 13 December 2021 - 04:02 PM, said:

As an experiment turn GC off, completely and see what happens. If you can keep track of objects created on the heap, you should be able to see if duplicates are being created. The IDE debugger should be able to show you that. In practice, as in runtime user experience, that is what I "see",ie duplication, and way MORE!


If the OR team needs a route for this sort of testing that has both huge terrain distances and tiles with thousands of objects and lots of textures, I can provide it. Send me a PM if you want it.

  • 8 Pages +
  • « First
  • 2
  • 3
  • 4
  • 5
  • 6
  • Last »
  • You cannot start a new topic
  • You cannot reply to this topic

1 User(s) are reading this topic
0 members, 1 guests, 0 anonymous users