Dealing with GUI lag and ways around it

Hello,


Right now I am running a simple application with a relatively simple GUI.  However, I have quite a few of the TMS Instrumentation controls on the main form of the GUI.  I have 3 CircularGauges, 3 LinearGauges, 2 charts and a progress bar.  All of these are being updated at live time based off a SQLite database and using livebindings to the fields in the database.  I noticed after I have all the gauges and charts linked up, that the GUI or refresh lag was starting to build up.

My question would be, is LiveBindings a good way to handle these gauges or is doing it manually a much better solution?  Right now I am just using a timer that updates each gauge every 500ms as a test.  I am changing the value of the gauges and after each gauges is updated, doing a single commit to the database off each gauges current value.  I can't really tell if the SQLite database is just slow, or if I am running into hardware limitations.

This application runs great on my desktop but I have a rather beefy desktop.  When I run it on my tablet, that is when the lag starts happening.  However, the application is truly only using about 24% of my CPU and 45MB of RAM.  I am trying to make this as seemless as possible.  If you need code samples, I would gladly give some of how it is running.  Also, I added a Camera feed, but that does not seem to add to the lag much, it just adds more memory usage.  I would like to use our hardware's full potential if possible and thought about multi-threading to make this run smoother.

All in all, does having 8 of the controls updating using LiveBindings rather quickly cause lag?  Is there a better way to handle it?  Thank you all for your help.

Sean M.

Hi, 


Did you run the test with and without the database update and see if there is any difference in performance? It could be possible that writing the a database through LiveBindings is causing the slowness, but it could also be possible that it's updating the gauges itself that is causing the slowness, it depends on many factors, the kind of graphics that are used and the amount of information in the charts.

Multi-threading could resolve this issue especially when you manage multiple extensive graphical objects simultaneously.

Kind Regards, 
Pieter

The issue with LiveBindings is that it is quite difficult to tell what is going on behind the scenes.

I'm not sure if LiveBindings would cause 8 separate form refreshes when the values of the 8 controls update (as opposed to one refresh only that would be necessary).
Have you tried to compare screen update behavior when you directly set the values of these TMS Instrumentation controls instead of via LiveBindings?

I have tried just about everything to focus the lag down, and I think it is just general lag...I have removed livebindings and the database and the camera feed, so literally it is just the 7 gauges and 2 charts moving and updating on a timer.  The lag still persists.


Let me ask this.  What is the proper way to create a TTHread for the GUI elements?  I know how to create a Thread, however, I am not sure how I want to split up the workload.  Do I want a thread for each gauge?  This is going to be running on a rather beefy tablet, but still needs to be able to run well on lower end devices.  My main concern was that the TMS Instrumentation was causing the lag.  I am not using any graphics or anything special.  I have just been the stock gauges that come with the instrumentation pack.

I basically have a blank FireMonkey form in C++ Builder XE8 with 3 Circular, 3 Linear, a Progress Bar, and 2 Charts that are moving based on a timer that is updating their values.  The timer is set to 500ms.  Every tick it gets calls a method to gradually increase their values.  I also have made carriage boxes with Pieters help that uses CurrentValue() to display the needles value.  I noticed more lag coming when I implemented the CurrentValue() method to display the needles value in a real time manner.

Let me know what you think is the best thing to do.  I hear that Multithreading GUI elements can be a hassle as you have to Synchronize() to the main thread every time you do something.

Thank you both.


Code Example of trying to contain to a thread:

void __fastcall TUpdateDBThread::Execute() {
// ---- Place thread code here ----
while (!Terminated) {
Sleep(500);
// do the acquiring
float currentGaugeValue = 0;
Form1->CentralGaugeFrame1->FDQuery1->SQL->Clear();
Form1->CentralGaugeFrame1->FDQuery1->SQL->Add(
"UPDATE GaugeValues SET CG1Val = (:CG1Val), CG2Val = (:CG2Val), FlowGaugeVal = (:FGVal), LG1Val = (:LG1Val), LG2Val = (:LG2Val), LG3Val = (:LG3Val), WaterMeterVal = (:GPMVal)"

Here is a sample of my methods that are changing the values and moving the gauges and charts:

float UpdateWaterMeter(float curVal)
{
float GPMNewValue;

if(curVal < 60)
{
GPMNewValue = curVal + 1.33;
}
else
{
GPMNewValue = 0;
}

return GPMNewValue;
}

void __fastcall TUpdateDBThread::MoveThrustChart()
{
Form1->CentralGaugeFrame1->ThrustChart->SerieByName[1]->AddPoint(Random(120));
Form1->CentralGaugeFrame1->ThrustChart->SerieByName[1]->MinX++;
Form1->CentralGaugeFrame1->ThrustChart->SerieByName[1]->MaxX++;
}
//---------------------------------------------------------------------------

void __fastcall TUpdateDBThread::MoveRotationChart()
{
Form1->CentralGaugeFrame1->RotationChart->SerieByName[1]->AddPoint(Random(120));
Form1->CentralGaugeFrame1->RotationChart->SerieByName[1]->MinX++;
Form1->CentralGaugeFrame1->RotationChart->SerieByName[1]->MaxX++;
}
);

currentGaugeValue = Form1->CentralGaugeFrame1->TMSFMXCircularGauge1->Value;
Form1->CentralGaugeFrame1->FDQuery1->Params->ParamByName("CG1Val")->AsFloat = UpdateCircularGauge1(currentGaugeValue);
currentGaugeValue = Form1->CentralGaugeFrame1->TMSFMXCircularGauge2->Value;
Form1->CentralGaugeFrame1->FDQuery1->Params->ParamByName("CG2Val")->AsFloat = UpdateCircularGauge2(currentGaugeValue);
currentGaugeValue = Form1->CentralGaugeFrame1->FlowGauge->Value;
Form1->CentralGaugeFrame1->FDQuery1->Params->ParamByName("FGVal")->AsFloat = UpdateFlowGauge(currentGaugeValue);
currentGaugeValue = Form1->TMSFMXLinearGauge1->Value;
Form1->CentralGaugeFrame1->FDQuery1->Params->ParamByName("LG1Val")->AsFloat = UpdateLinearGauge1(currentGaugeValue);
currentGaugeValue = Form1->CentralGaugeFrame1->TMSFMXLinearGauge2->Value;
Form1->CentralGaugeFrame1->FDQuery1->Params->ParamByName("LG2Val")->AsFloat = UpdateLinearGauge2(currentGaugeValue);
currentGaugeValue = Form1->CentralGaugeFrame1->TMSFMXLinearGauge3->Value;
Form1->CentralGaugeFrame1->FDQuery1->Params->ParamByName("LG3Val")->AsFloat = UpdateLinearGauge3(currentGaugeValue);
currentGaugeValue = Form1->CentralGaugeFrame1->waterprogress->Value;
Form1->CentralGaugeFrame1->FDQuery1->Params->ParamByName("GPMVal")->AsFloat = UpdateWaterMeter(currentGaugeValue);

Form1->CentralGaugeFrame1->FDQuery1->ExecSQL();
Form1->CentralGaugeFrame1->FDQuery1->Close();
Synchronize(UpdateDBValues);
Synchronize(MoveRotationChart);
Synchronize(MoveThrustChart);
}
}


I dont know why it posted part of my methods in the middle of the execute method.  Is there a way to edit posts?