Problem with graph c#

Asked

Viewed 128 times

2

Good morning guys, I’m developing a program in which should be plotted several line graphics(x,y) on the screen, the y axis corresponds to serial port where is connected an Arduino UNO. As an example, I need a graph where I have 6000 dots drawn in 20 seconds (about 3,333 ms each new dot). The problem is that to draw the 6000 points the program is taking about 35 seconds. Follow graphControl1 control call drawing graph.

private void timerDRAW_Tick(object sender, EventArgs e)
{
    //timerDRAW com intervalo de 3 ms
    SerialCOM.DataReceived += new SerialDataReceivedEventHandler(SerialCOM_DataReceived);
}

private void SerialCOM_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
    if (SerialCOM.IsOpen)
    {
        SerialPort sData = (SerialPort)sender;
        {
            string RxString = sData.ReadLine();
            bool result = int.TryParse(RxString, out int data);
            if (result)
            {
                var atualdata = 5.0f * data / 1023.0f;
                graphControl1.AddValue(atualdata, atualdata, atualdata, atualdata);
            }
        }
    }
}

I’ve tried several code modifications. I’ve received tips that the Datareceived method can be optimized to improve graph performance, but I’m unable to implement another solution.

I do not know if only this information is enough to solve my problem because I am a beginner. The graphControl control is a bit extensive so I won’t be attaching, but if someone is available to help I can send the code. Thank you guys !!

EDIT: I’m uploading graphControl control code for analysis

public class GraphControl : Control
{
    #region DECLARAÇAO DE VARIAVEIS GLOBAIS

    int contador = 0;
    private int _minValue = 0;
    private int _maxValue = 10;
    private int _dataCount = 6000;
    private List<float> _values1 = new List<float>();
    private List<float> _values2 = new List<float>();
    private List<float> _values3 = new List<float>();
    private List<float> _values4 = new List<float>();

    #endregion

    public int MinValue
    {
        get => _minValue;
        set
        {
            _minValue = value;
            Invalidate();
        }
    }

    public int MaxValue
    {
        get => _maxValue;
        set
        {
            _maxValue = value;
            Invalidate();
        }
    }

    public int DataCount
    {
        get => _dataCount;
        set
        {
            _dataCount = value;
            Invalidate();
        }
    }

    public GraphControl()
    {
        Size = new System.Drawing.Size(498, 264);
        SetStyle(ControlStyles.OptimizedDoubleBuffer | ControlStyles.ResizeRedraw, true);
    }

    public void AddValue(float value1, float value2, float value3, float value4)
    {
        _values1.Add(value1);
        _values2.Add(value2);
        _values3.Add(value3);
        _values4.Add(value4);
        contador++;
        if (contador == 4)
        {
            Invalidate();
            contador = 0;
        }
    }

    protected override void OnPaint(PaintEventArgs e)
    {
        e.Graphics.SmoothingMode = SmoothingMode.AntiAlias;
        var wid = (float)Width / (float)_dataCount;
        var total = 5;

        //-----------------------------------------1--------------------------------------------------------------------

        var lastPoint1 = new PointF(0F, (float)(2 * Height / 5) * 0.5F);
        var lastPoint2 = new PointF(0F, (float)(Height / 2));
        var lastPoint3 = new PointF(0F, (float)(7 * Height / 10));
        var lastPoint4 = new PointF(0F, (float)(9 * Height / 10));
        PointF newPoint1 = new PointF();
        PointF newPoint2 = new PointF();
        PointF newPoint3 = new PointF();
        PointF newPoint4 = new PointF();

        var idInit = _values1.Count - _dataCount;

        if (idInit < 0)
            idInit = 0;

        for (int i = idInit, a = 0; i < _values1.Count; i++, a++)
        {
            var value = (float)(_values1[i]);
            var porcent = value / total;

            if (porcent > 1) porcent = 1;
            var hg = porcent * (2 * Height / 5);

            newPoint1.X = (a + 1) * wid;

            if (porcent >= 1) newPoint1.Y = 2 * Height / 5 - hg;
            else newPoint1.Y = 2 * Height / 5 - hg - 1;

            using (var p = new Pen(Color.Lime, 0.1f)) e.Graphics.DrawLine(p, lastPoint1, newPoint1);

            lastPoint1 = newPoint1;

            //------------------------------------------------------------------------------------

            value = (float)(_values2[i]);
            porcent = value / total;

            hg = porcent * (Height / 5);

            newPoint2.X = (a + 1) * wid;

            newPoint2.Y = 3 * Height / 5 - hg;

            using (var p = new Pen(Color.Lime, 0.1f)) e.Graphics.DrawLine(p, lastPoint2, newPoint2);

            lastPoint2 = newPoint2;

            //------------------------------------------------------------------------------------

            value = (float)(_values3[i]);
            porcent = value / total;

            hg = porcent * (Height / 5);

            newPoint3.X = (a + 1) * wid;

            newPoint3.Y = 4 * Height / 5 - hg;

            using (var p = new Pen(Color.Lime, 0.1f)) e.Graphics.DrawLine(p, lastPoint3, newPoint3);

            lastPoint3 = newPoint3;

            //------------------------------------------------------------------------------------

            value = (float)(_values4[i]);
            porcent = value / total;

            hg = porcent * (Height / 5);

            newPoint4.X = (a + 1) * wid;

            newPoint4.Y = Height - hg -1;

            using (var p = new Pen(Color.Lime, 0.1f)) e.Graphics.DrawLine(p, lastPoint4, newPoint4);

            lastPoint4 = newPoint4;
        }

        base.OnPaint(e);
        }
    }
}

When sending the values to graphControl I am using the 4 equal values, but it is only a test situation. If anyone can help me, I’d appreciate it.

  • Nothing in this code indicates any problem (that can be identified).

  • Vish guy, I’ll post the code from the graphControl control and if possible take a look at me, please.

  • I would like to know the performance of performing the "Invalidate()" method only once after loading the data.

  • I’m using the Invalidate( ) method every 4 calls of the Addvalue( ) method to be able to produce a graph effect running on the screen, I need to update the data on the screen at all times. If I use Invalidate( ) in all Addvalue ( ) calls the program slows down, the buttons lock and if I use only once after the data load I can’t produce the effect I want.

  • The effect would be more or less like a Seismograph. https://www.youtube.com/watch?v=0cSlxPeqHA8

  • I can’t really know what’s going on, my initial attempt would be to check if with each addition, he’s not drawing the whole graph again (idInit=0), should draw only the part that was added, or limit the drawing only to a specific size on the screen...

  • Felipe, I thought it was necessary, but my comment was to identify if the bottleneck is in the presentation layer. You still have the "Invalidates()" of gets Min, Max and Count.

  • I have integration with Arduino and I do posts directly in a micro service, consuming it by applications, distributed, asynchronously. Could be a way out..

  • I understood Andre, I commented the Invalidates( ) of gets Min, Max and Count and left only one Invalidate( ) after the data load, but even so the program still takes about 30 seconds to reach 6000 points. It would then be a problem in the presentation layer?

Show 4 more comments

1 answer

2

Code profile is the path I suggest. Use the Clrprofile which will allow you to collect the execution trace and thereby allow you to see where exactly the bottlenecks occur.
My second suggestion. Log the code with the execution times of each part involved (How do I Measure how long a Function is running?). So you’ll see where the times are being spent.

  • thanks friend, I’ll take a look

  • The clrProfile Histogram shows the System.Drawing.Pen at 91%. It would then be the way to draw the neck?

  • I’m not from the graphic area, but if it is shown, it must be. It’s been a long time, but when I built charts using C#, I used Microsoft Chart Controls for . NET Framework and had no performance problems.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.