Author Topic: High CPU usage ?  (Read 3014 times)

thug_

  • Newbie
  • *
  • Posts: 30
    • View Profile
High CPU usage ?
« on: March 02, 2017, 05:06:43 AM »
Hi All,

I am running application which is reading 17 registries from PLC every 100ms. PLC type is Allen Bradley MicroLogix 1200, and I am using Serial to USB connection with PLC. I am using SerialDF1forSLCMicroCom driver form AdvancedHMI, and BeginRead method for reading those registries.

When I run application my CPU usage is around 15- 20% which is little bit high for what I need. I ran performance profiler from red gate on it and it is showing that AdvancedHMIDrivers.S erialDF1forSLCMicroCom.OnDataReceived (PlcComEventArgs e) is "hot" and taking 34,5% time with children. It is everything running in WPF app.

Any suggestion how I could decrease usage of CPU?

Thanks



Archie

  • Administrator
  • Hero Member
  • *****
  • Posts: 5322
    • View Profile
    • AdvancedHMI
Re: High CPU usage ?
« Reply #1 on: March 02, 2017, 05:25:10 AM »
Temporarily comment out your code in the DataReceived event handler and see what effect that has.

thug_

  • Newbie
  • *
  • Posts: 30
    • View Profile
Re: High CPU usage ?
« Reply #2 on: March 02, 2017, 05:31:38 AM »
In that event handler I am assigning all values, which will later on be passed to UI, so basically nothing is happening if I comment out that part of code, I did and I run app, as it is expected CPU = 0, but I am not reading anything from PLC in that case.

Archie

  • Administrator
  • Hero Member
  • *****
  • Posts: 5322
    • View Profile
    • AdvancedHMI
Re: High CPU usage ?
« Reply #3 on: March 02, 2017, 07:48:58 AM »
I'm not sure if I understand fully when you say you are not reading anything from the PLC.....Are you calling the BeginRead in the DataReceived event handler?
« Last Edit: March 02, 2017, 07:51:13 AM by Archie »

thug_

  • Newbie
  • *
  • Posts: 30
    • View Profile
Re: High CPU usage ?
« Reply #4 on: March 02, 2017, 08:57:54 AM »
          public SerialDF1forSLCMicroCom m_plc = new SerialDF1forSLCMicroCom();
          public event EventHandler<CameraResultsEventArgs> ResultsAvailable;
          System.Windows.Threading.DispatcherTimer plcPoll = new System.Windows.Threading.DispatcherTimer();
           public void Read()
           {
           
            m_plc.Write("N7:0", "100");
            m_plc.Write("N7:14", "100");
            m_plc.Write("N7:15", "100");
            m_plc.Write("N7:16", "100");
            plcPoll.Interval = TimeSpan.FromMilliseconds(100);
            plcPoll.IsEnabled = true;
            plcPoll.Tick += plcPoll_Tick;
            m_plc.DataReceived += m_plc_DataRecieved;
            plcPoll.Start();
        }

        void plcPoll_Tick(object sender, EventArgs e)
        {
            m_plc.BeginRead("N7:0", 17);
            //m_plc.BeginRead("C5:0.ACC", 7);
         
        }

        void m_plc_DataRecieved(object sender, MfgControl.AdvancedHMI.Drivers.Common.PlcComEventArgs e)
        {
            CamCollection values = new CamCollection();

            try
            {
                if (e.PlcAddress == "N7:0" && e.Values.Count == 17)
                {
                    values.Camera1.Trigger = e.Values[0];
                    values.Camera1.CurInspectionTime = e.Values[4];
                    values.Camera1.MaxInspectionTime = e.Values[3];

                    values.Camera2.Trigger = e.Values[14];
                    values.Camera2.MaxInspectionTime = e.Values[6];
                    values.Camera2.CurInspectionTime = e.Values[7];

                    values.Camera4.Trigger = e.Values[16];
                    values.Camera4.CurInspectionTime = e.Values[13];
                    values.Camera4.MaxInspectionTime = e.Values[12];

                    values.Camera3.Trigger = e.Values[15];
                    values.Camera3.CurInspectionTime = e.Values[10];
                    values.Camera3.MaxInspectionTime = e.Values[9];

                    if (ResultsAvailable != null)
                        ResultsAvailable(this, new CameraResultsEventArgs { Camera1 = values.Camera1, Camera2 = values.Camera2, Camera3 = values.Camera3, Camera4 = values.Camera4 });

                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(String.Format("Error reading nValues: {0}", ex.ToString()));
                plcPoll.Stop();
            }


That's the part of code where is reading done.
« Last Edit: March 02, 2017, 08:59:58 AM by thug_ »

Archie

  • Administrator
  • Hero Member
  • *****
  • Posts: 5322
    • View Profile
    • AdvancedHMI
Re: High CPU usage ?
« Reply #5 on: March 02, 2017, 09:02:07 AM »
Try just commenting out this line to see what effect it has on CPU usage:

 if (ResultsAvailable != null)
                        ResultsAvailable(this, new CameraResultsEventArgs { Camera1 = values.Camera1, Camera2 = values.Camera2, Camera3 = values.Camera3, Camera4 = values.Camera4 });

thug_

  • Newbie
  • *
  • Posts: 30
    • View Profile
Re: High CPU usage ?
« Reply #6 on: March 02, 2017, 09:26:06 AM »
It decreased but it is still around 7- 10..

Archie

  • Administrator
  • Hero Member
  • *****
  • Posts: 5322
    • View Profile
    • AdvancedHMI
Re: High CPU usage ?
« Reply #7 on: March 02, 2017, 09:31:00 AM »
Are you only calling Read a single time. If it is called more than once, you will accumulate these timers because the only time plcPoll is stopped is during an exception.

Also have you tried using subscriptions with PollRateOverride set to 100 to let the driver handle the updates using it's own background thread?

thug_

  • Newbie
  • *
  • Posts: 30
    • View Profile
Re: High CPU usage ?
« Reply #8 on: March 02, 2017, 10:16:36 AM »
No I am just calling once when btnRead is pressed, that is the part of code when is happening :

  private void btnReadPlc_Click(object sender, RoutedEventArgs e)
        {
            _wp = new WriteReadPlc();
            //_draw.DrawDynamicGraph();
            _wp.ResultsAvailable+=wp_ResultsAvailable;
            try
            {
                Task.Factory.StartNew(() => {
                    _wp.Read();                 
                });
            }
            catch (Exception ex)
            {
                MessageBox.Show(String.Format("Error reading from PLC"));     
            }
}

I tried to use subscriptions but I don't how to read 17 registries, with subscription, do I need to create for every registry one subscription, or there is some way to read all of them with one subscription ?


Archie

  • Administrator
  • Hero Member
  • *****
  • Posts: 5322
    • View Profile
    • AdvancedHMI
Re: High CPU usage ?
« Reply #9 on: March 02, 2017, 02:27:58 PM »
What version of AdvancedHMI are you using? Various sub-versions of 3.99 have fixed issues related to asynchronous reading and high CPU usage. Although I do not think any of them will pertain to what you are seeing.

According to your code, each time the button is clicked, you will launch another thread with a timer that will add more reading. So a second click will then read 17 values every 50ms.

A subscription can read 17 values by specifying the number of elements in the subscribe call.

thug_

  • Newbie
  • *
  • Posts: 30
    • View Profile
Re: High CPU usage ?
« Reply #10 on: March 03, 2017, 04:33:51 AM »
As I said I tried with subscription but I couldn't make to work

   //subscriptionTime = m_plc.Subscribe("N7:", 17, 100, plc_GigeOneDataRecieved);

This the line of code how I was trying to do, later in plc_GigeOneDataRecieved I was just assigning values to my variables. But I could get this work only when I read 1 element, so instead of 17 if I give 1 as numOfElements, it was working but 17 no. I am using 3.9.9.17 version of AdvancedHMI, later today I will try to get newset version and try again with subscribtions.

bachphi

  • Hero Member
  • *****
  • Posts: 671
    • View Profile
Re: High CPU usage ?
« Reply #11 on: March 03, 2017, 12:58:33 PM »
try N7:0

But I would use a Bool bit to trigger your subscribe, then in DataChanged event , do a beginread (ex. PLC.BeginRead("Sta03Data[0]", 17)),

then catch returned values in DataReceived event with

If e.PlcAddress = "Sta03Data[0]" Then

            _serialNumber = e.Values(0)
            _pressure = e.Values(1)
            _flow = e.Values(2)
===================================================
This is NOT alt.read.my.mind.
No such thing is sh^t-for-brains unless you are posting to alt.read.my.mind.
===================================================

thug_

  • Newbie
  • *
  • Posts: 30
    • View Profile
Re: High CPU usage ?
« Reply #12 on: March 03, 2017, 08:41:37 PM »
I tried N7:0 as well but I just get a value for N7:0 others I am not getting. I didn't understand the part with bool bit to trigger subscribe, can you just give an example with code it will be easier for me to understand.

Thanks.

Archie

  • Administrator
  • Hero Member
  • *****
  • Posts: 5322
    • View Profile
    • AdvancedHMI
Re: High CPU usage ?
« Reply #13 on: March 03, 2017, 08:46:57 PM »
I tried N7:0 as well but I just get a value for N7:0 others I am not getting. I didn't understand the part with bool bit to trigger subscribe, can you just give an example with code it will be easier for me to understand.
When your DataReceived event fires, is there only 1 element in e.Values ?

thug_

  • Newbie
  • *
  • Posts: 30
    • View Profile
Re: High CPU usage ?
« Reply #14 on: March 03, 2017, 10:53:38 PM »
Yes Archie it is only 1 element in e.Values, when DataRecived event fires.