Search code examples
c#wpfjson.netgarbage-collection

C# garbage collecting reasons?


I have the following code as a WPF app.

using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Windows.Threading;

namespace TestLeak {
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window {
        public MainWindow() {
            InitializeComponent();

            Random RND = new Random();

            int SIZE = 100000;

            double fValue0 = 0;
            double fValue1 = 0;
            double fValue2 = 0;

            JArray aValues0 = new JArray(new double[SIZE]);
            JArray aValues1 = new JArray(new double[SIZE]);
            JArray aValues2 = new JArray(new double[SIZE]);
            JArray aValues = new JArray();
            aValues.Add(aValues0);
            aValues.Add(aValues1);
            aValues.Add(aValues2);

            DispatcherTimer oTimer = new DispatcherTimer(DispatcherPriority.Normal);
            oTimer.Tick += new EventHandler((oSender, aArgs) => {
                for (int i = 0; i < SIZE; i++) {
                    fValue0 += 1;
                    fValue1 += 1;
                    fValue2 += 1;
                    aValues0[i] = fValue0;
                    aValues1[i] = fValue1;
                    aValues2[i] = fValue2;
                }
            });
            oTimer.Interval = TimeSpan.FromMilliseconds(1000);
            oTimer.Start();
        }
    }
}

I have no idea why the GC needs to work that hard, what is it collecting? It's just basic assignment and overwriting (kind of an)array values. Could it be an issue with NewtonSoft Jarray objects?

The issue is that for my app, the interval is way smaller (aiming for ~16ms) but on each step the GC alone takes 40+ms to complete.

Thank you!

Garbage Collection at work


Solution

  • You are creating 300k objects every tick because JArray.operator[] is of type JToken, which is a reference class. You're assigning doubles to them for every item of every one of your three arrays, which implicitly creates JValue instances:

        public static implicit operator JToken(double value)
        {
            return new JValue(value);
        }
    

    That's what the garbage collector is collecting.