question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Memory leak in DrawingContext.DrawGeometry

See original GitHub issue

Hello, there seems to be some sort of leak when repeatedly using the DrawingContext.DrawGeometry method to fill geometries with different shapes.

To reproduce, add the following Control to an empty Window:

public class TestControl : Control
    {
        Point mousePosition = new Point();
        Random rnd = new Random();
        int segmentCount = 20;
        double radius = 100;

        protected override void OnPointerMoved(PointerEventArgs e)
        {
            mousePosition = e.GetPosition(this);
            this.InvalidateVisual();
        }

        public override void Render(DrawingContext context)
        {
            //So that we capture the PointerMoved events
            context.FillRectangle(Brushes.White, new Rect(0, 0, this.Bounds.Width, this.Bounds.Height));

            PathFigure fig = new PathFigure() { StartPoint = new Point(mousePosition.X + radius, mousePosition.Y) };

            for (int i = 0; i < segmentCount; i++)
            {
                //Geometry always has the same shape: no leak
                //fig.Segments.Add(new LineSegment() { Point = new Point(mousePosition.X + radius * Math.Cos(i * 2 * Math.PI / segmentCount), mousePosition.Y + radius * Math.Sin(i * 2 * Math.PI / segmentCount)) });

                //Geometry shape changes at every redraw: leak!
                fig.Segments.Add(new LineSegment() { Point = new Point(mousePosition.X + radius * Math.Cos(i * 2 * Math.PI / segmentCount) * rnd.NextDouble(), mousePosition.Y + radius * Math.Sin(i * 2 * Math.PI / segmentCount) * rnd.NextDouble()) });

            }

            fig.IsClosed = true;

            PathGeometry testGeometry = new PathGeometry();
            testGeometry.Figures.Add(fig);

            //Stroke: no leak
            //context.DrawGeometry(null, new Pen(Brushes.Blue), testGeometry);

            //Fill: leak!
            context.DrawGeometry(Brushes.Blue, null, testGeometry);
            
        }
    }

Then run the program and quickly move the mouse around in the window. Each time the mouse moves, the control is repainted with a geometry with a different (random) shape; at the same time, the memory usage will go up steadily.

I had a look with the profiler, and it seems to be mostly unmanaged memory:

image

That Dictionary<IntPtr, WeakReference> SkiaSharp.HandleDictionary.instances looks suspicious…

I first noticed this while using AvaloniaEdit: the SelectionLayer there draws the text selection using DrawGeometry, and this causes the control to use increasing amounts of memory as the user selects text regions with different shapes.

The issue:

  • Happens with Avalonia 0.10.0-preview1 - 0.10.0-preview3, but not with 0.9.12
  • Happens on both Windows 10 and Ubuntu 20.04
  • Does not happen if the geometry has the same shape, even though the points making it up are still computed at every redraw: if you replace the relevant line with the commented line in the code above, the control draws a 20-sided polygon centered at the mouse pointer rather than a random shape; in this case, the leak does not occur.
  • Does not happen if the geometry is stroked rather than filled (see comments in code).

Issue Analytics

  • State:closed
  • Created 3 years ago
  • Comments:8 (7 by maintainers)

github_iconTop GitHub Comments

2reactions
grokyscommented, Sep 1, 2020

BTW, thanks for the fantasic repro @arklumpus !

0reactions
wieslawsoltescommented, Sep 3, 2020

I think there is still some leak, my code, everything is cached:

https://github.com/wieslawsoltes/Core2D/blob/404ad16d8d8b205ec7858b6f3355020c31c0be65/src/Core2D.UI/Renderer/Nodes/PathDrawNode.cs#L32

Got 57.5MB to 1.6GB memory usage jump in seconds.

Core2D-GPU-DrawGeometry

Read more comments on GitHub >

github_iconTop Results From Across the Web

Does DrawingContext.DrawText have a memory leak?
I doubt there is a memory leak in dc.DrawText as this is very common in applications, Its possible somthing else is holding on...
Read more >
DrawingContext Class - Typedescriptor
DrawingContext Class sealed ... by the DrawingContext. DrawGeometry(IBrush, Pen, Geometry) Draws a geometry. ... Memory leak in DrawingContext.DrawGeometry ...
Read more >
CodeProject
... use weak events 85 // to prevent memory leaks when the text area control gets dropped ... DrawingContext drawingContext) 188 { 189...
Read more >
Memory Leak by drawing pictures - NI Community
I am experiencing out of memory after a couple of hours when I start my program. In my program I am drawing a...
Read more >
MEMORY LEAK: I'm stumped on this one. : r/gamemaker
Issue: The game builds up memory, slowing down until it crashes. The surface is not deleting. One Object, oBackground, controls the surface. It ......
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found