TomCatFort's picture

Constant memory allocations.

Hello there. I'm started making a hobby project using OpenTK with C# and Framework 3.5 and I soon noticed something strange that is now driving me crazy: I did some test with the building blocks of my project (various drawing classes) and I saw that the memory usage goes up at a constant rate with a considerable rate. I thought it is imposable, I do not allocate that memory, i was very careful about allocating. So I used a .NET memory profiler and I saw the live instance number goes up in a straight line and there is a more or less constant level of allocation. So I removed all my test code so I have these game loop functions now:

protected override void OnUpdateFrame(FrameEventArgs e)
{
    base.OnUpdateFrame(e);
}
 
protected override void OnRenderFrame(FrameEventArgs e)
{
    GL.Clear(ClearBufferMask.ColorBufferBit);
    base.OnRenderFrame(e);
    SwapBuffers();
}

But the allocations still happens, so i removed GL.Clear and SwapBuffers(), but allocation still occurs. I have no other thread or function that could make it. The memory profiler also showed me that the number of my objects are constant, I was also unable to determinate the type of the live instances that is constantly allocated; so I named them ghosts are they seemingly come from nothing and die when GC kills them in generation zero. According to my loose calculation it is about 4 kibibytes / 3 sec with the code above. More strangely, a few times when I run my program it doesn't happen, but most times it happens regardless of build mode or how do i start it (from IDE or from file explores using the .exe). It also gives an average of 6% CPU usage on a dual core CPU, and I cant believe that doing nothing but cleaning the screen with adaptive VSync (adapts to On) using 6% CPU (sometimes 9%).
Honestly! Now it is only happens when I'm not doing a full profiling on the application, when I run it normally the Task Manager show the continuous growing of memory, while profiling it it runs normally. The hell is happening???!!!


Comments

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.
the Fiddler's picture

Which version of OpenTK are you using? Needless to say, this is not supposed to happen - GameWindow was written precisely to avoid such memory allocations!

I just tested the simplest example that comes with OpenTK (immediate mode cube, svn trunk) and wasn't able to reproduce either issue. Memory allocations remain flat and CPU usage is 0% (release mode) or 3% (debug mode). The profiler doesn't reveal any unaccounted allocations either. x86 and x64 modes perform identically.

I don't know what to suggest here. I've been very careful to avoid allocations after initialization and have used the library in a few performance-sensitive projects where even gen-0 collections could have caused problems.

Does an empty GameWindow suffer from this, too?

using (var gw = new GameWindow())
{
    gw.VSync = VSyncMode.On;
    gw.Run();
}
TomCatFort's picture

I created a project for testing:

using System;
using OpenTK;
 
namespace Test541
{
    sealed class Program : GameWindow
    {
        static int Main()
        {
            using (var p = new Program())
            {
                p.VSync = VSyncMode.Off; //Off, because this generates garbage faster.
                p.Run();
            }
            return 0;
        }
 
        protected override void OnRenderFrame(FrameEventArgs e)
        {
            base.OnRenderFrame(e);
            SwapBuffers(); //This cause garbage. If this not called, no garbage.
        }
    }
}

It even happens in the examples (I tried the 1st, the rotating simple cube). And I don't call SwapBuffers() then no garbage created. But every time I call it, some garbage generated.
And the version is 1.0. I downloaded it last week from the main page of the OpenTK site.

EDIT: I checked out the source from SVN, compiled it in release mode. And the problems happens with a freshly compiled trunk version. Can it caused by driver or some other system component?
EDIT: I restarted a few things (IDE), unistaled v1.0. And looks like the phenomenon stopped.

the Fiddler's picture

Drivers have been known to leak memory before in WGL so I wouldn't be surprised if this was a driver bug. What video card, OS and drivers are you using?

For the record, SwapBuffers calls this code on Windows:

        // GameWindow.cs
        public void SwapBuffers()
        {
            EnsureUndisposed(); // if (IsDisposed) throw new ObjectDisposedException(GetType().Name);
            this.Context.SwapBuffers();
        }
 
        // Platform/Windows/WinGLContext.cs
        public override void SwapBuffers()
        {
            if (!Functions.SwapBuffers(DeviceContext))
                throw new GraphicsContextException(String.Format(
                    "Failed to swap buffers for context {0} current. Error: {1}", this, Marshal.GetLastWin32Error()));
        }
 
        // Platform/Windows/API.cs
        [SuppressUnmanagedCodeSecurity]
        [DllImport("gdi32.dll", SetLastError=true)]
        [return: MarshalAs(UnmanagedType.Bool)]
        internal static extern bool SwapBuffers(IntPtr dc);

I don't really see how this code could result in memory allocations. I'm inclined to believe this is a driver issue but I'll try to reproduce on a couple of different machines tomorrow.

TomCatFort's picture

OS: Windows 7 Ultimate 64bit.
Video card: GeForce 9600M GT.
Driver version: 196.62 (official driver).