Memory/resource leak when pointer moves?

Gauge for WPF Forum

Posted 11 years ago by Sean McLeod
Version: 4.0.0457
Platform: .NET 3.5
Environment: Windows Vista (32-bit)
Avatar
Hi

I've used the gauges from the automotive sample pretty much as is for a boat engine simulator for a customer. Basically 2 tachometer gauges with embedded temperature gauges, 2 oil pressure gauges and a speedometer gauge.

The only real change is that I've disabled the dampening effect by setting both DampeningMaximumDuration and DampeningMinimumDuration to 0 on all the gauges.

The simulator reads the throttle positions from some external hardware and then drives the RPM, speedometer, etc. gauges. every 30ms based on a DispatchTimer.

What I've noticed is that if there is no throttle movement and in other words no movement of the pointers/needles on the gauges then the simulator runs fine for hours with CPU usage very low and steady and no increase in private bytes and the DispatchTimer firing very consistently every 30ms.

However with normal throttle movements after about 5 minutes I notice that the DispatchTimer event starts coming through very erratically, instead of a steady and consistent 30ms suddenly you see periods of it only arriving every 150-300ms. Secondly the CPU usage jumps up 20-30% and lastly if you take a look at memory usage in terms of private bytes you notice a steady and pretty continous climb.

The gauges pointers are data bound to a class implementing the standard INotifyPropertyChanged interface.

    public class SimGaugeData : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;

        double _portRPM;
        public double PortRPM
        {
            get { return _portRPM; }
            set
            {
                if (value != _portRPM)
                {
                    _portRPM = value;
                    OnPropertyChanged("PortRPM");
                }
            }
        }

        protected void OnPropertyChanged(string propName)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(propName));
            }
        }
    }

To reproduce the problem without having to read from any external hardware etc. I just set the simulated gauge values to random values in the gauge's range in the DispatchTimer's event handler which fires every 30ms and the problem starts occuring within 30-60secs now.

Random random = new Random();
double _scale = 1.0;

void _simDataRefreshTimer_Tick(object sender, EventArgs e)
{
   _simGaugeData.PortRPM = random.NextDouble() * 6700.0 * _scale;
   _simGaugeData.PortWaterTemp = random.NextDouble() * 100.0 * _scale;
   _simGaugeData.PortOilPressure = random.NextDouble() * 120.0 * _scale;
   .......
}
The _scale member is toggled between -1.0 and 1.0 and while it's set to -1.0 the values are all negative making them out of range for the gauge pointer so the pointer doesn't move but all the data binding notifications happen and the simulator runs for hours in this state without any increase in private memory, without any cpu utilisation increase and with consistent DisptachTimer events.

But as soon as it's toggled to 1.0 the issues become apparent within 30-60secs.

So it appears that there is some memory leak or resource leak in terms of WPF geometry/visuals whenever the pointer moves.

I haven't had a chance to run a .Net memory profiler or WPFPerf to investigate further since I'm still busy finishing the simulation and hardware interfacing portions.

Thanks

Comments (6)

Posted 11 years ago by Actipro Software Support - Cleveland, OH, USA
Avatar
Hi Sean,

1. There is an issue with using HandoffBehavior.Compose when applying a new Storyboard that causes the "leak". We added a workaround so that the objects in question will be
released and available for garbage collection.

2. Previously, when the DampeningMaximumDuration is set to 0 the pointers would still animate to their new location, with a duration of 0. This apparently still consumes about the same CPU as when the duration is greater than 0. To workaround this issue, we now explicitly set the value when DampeningMaximumDuration is 0, which consumes alot less CPU.

These fixes will be in the next maintenance release.

Thanks for bringing this to our attention.


Actipro Software Support

Posted 11 years ago by Sean McLeod
Avatar
Hi

So just to confirm this fix to bypass the animation isn't in the recently released 4.5 version?

If not do you have a rough estimate of when the next maintenance release will be ready?

The reason I ask is because my client is launching their product at an international boat in Miami next week Mon.

As a temporary work around I only update the gauges every 150ms now instead of every 30ms which allows the simulator to run for roughly 25 minutes of normal use before they have to restart the application which is not ideal.

Thanks
Posted 11 years ago by Actipro Software Support - Cleveland, OH, USA
Avatar
Hi Sean,

Correct, it is not in build 470. It will be in build 471, which we're trying to get out this week yet.

If you don't see it released by Friday, contact us via email and perhaps we can get you a preview build.


Actipro Software Support

Posted 11 years ago by Sean McLeod
Avatar
Hi

That would be perfect. Ideally an early Friday morning release since time zone wise I'm in Cape Town South Africa ;-)

Cheers
Posted 11 years ago by D
Avatar
I've had someone point out something similar with a gauge I've worked on. Using a CircularPointerGauge, I have set it up to receive messages from another application using UDP. The gauge updates every time a message is received through the UDP connection...the message transmission speed to my gauge is about 8Hz. The gauge consistently uses between 20 - 40% CPU when data is being received that is making the pointer needle move. This doesn't happen when the Digital Gauge is used, and hasn't seemed to be a problem with the LinearGauge, either. The data rate could be part of the problem, but it seems that something like the pointer needle animation could be contributing to the processor/memory usage as well. I would be curious to find out more about this issue.
Posted 11 years ago by Actipro Software Support - Cleveland, OH, USA
Avatar
Hi D,

This issue should have be resolved with the latest release. If you have pointer animation enabled and have several updates per second, then the CPU usage could reach the ranges you specified. Depending on the frequency of the updates, you would probably need to disable the animations by setting DampeningMaximumDuration to 0.

The original issue of this forum post was that the animation was being used even when DampeningMaximumDuration was set to 0, therefore the CPU usage was higher than it needed to be (because we could skip the animation altogether).

Additionally, the code between LinearGauge and CircularGauge is nearly identical, with the only real difference being in the rendering code. There is obviously more "complicated" math going on with the CircularGauge though, since it needs to calculate angles as opposed to x/y offsets.

If you have a specific issue you are seeing, please email over a sample project to our support address so we can take a look.


Actipro Software Support

The latest build of this product (v2019.1 build 0683) was released 14 days ago, which was after the last post in this thread.

Add Comment

Please log in to a validated account to post comments.