alternative to software polling to check variable changes?
alternative to software polling to check variable changes?
Hi,
I have been trying out various solutions to monitor revpi IOs via software without draining to much CPU
As far as I have seen and has been mentioned (see viewtopic.php?f=19&t=227&p=835&hilit=events#p835) the only viable approach is to regularly poll the driver file descriptor for changes (/dev/piControl0).
On a revpi core this has proven to consume plenty of CPU time, the LightSiwtch.c example provided with an infinite loop without a wait like "while(1){...}" drains the CPU (40%) and it is impractical.
Given that the "harwdare" polling time between the revpi core and the IO modules is around 10ms if I am not wrong a while(1) makes little sense, but even with a delay of 10ms the CPU is quite stressed (say 16% with a loop written in the Go language). A reasonable time of 50ms (a button debounce) still takes up 6% of the CPU most of the time for nothing.
Monitoring the file system for changes with system calls (epoll system call on inotify file descriptors, tools like fswatch) does not seem to be an option, am I correct?
Is polling at regular intervals in software the only way of checking for variable changes then?
I think it would be good if the driver supported epoll file descriptors to avoid wasting CPU time in software loops, to me this approach seems a real waste.
Cheers
Enrico
I have been trying out various solutions to monitor revpi IOs via software without draining to much CPU
As far as I have seen and has been mentioned (see viewtopic.php?f=19&t=227&p=835&hilit=events#p835) the only viable approach is to regularly poll the driver file descriptor for changes (/dev/piControl0).
On a revpi core this has proven to consume plenty of CPU time, the LightSiwtch.c example provided with an infinite loop without a wait like "while(1){...}" drains the CPU (40%) and it is impractical.
Given that the "harwdare" polling time between the revpi core and the IO modules is around 10ms if I am not wrong a while(1) makes little sense, but even with a delay of 10ms the CPU is quite stressed (say 16% with a loop written in the Go language). A reasonable time of 50ms (a button debounce) still takes up 6% of the CPU most of the time for nothing.
Monitoring the file system for changes with system calls (epoll system call on inotify file descriptors, tools like fswatch) does not seem to be an option, am I correct?
Is polling at regular intervals in software the only way of checking for variable changes then?
I think it would be good if the driver supported epoll file descriptors to avoid wasting CPU time in software loops, to me this approach seems a real waste.
Cheers
Enrico
Re: alternative to software polling to check variable changes?
just let me give some comments to your statements and question:
First of all, yes there will be a possibility soon to call IOCTLs which let your task wait for a certain IO change. It will work like the current IOCTL used to monitor picontrol resets. You start the task which is doing the call and the call returns with the new value as soon as there is one. So this is close to interrupt style operation.
Then I think you need to think different in a multi tasking operation system device. It seems to me that your roots are coming from programming small embedded systems. With a complex system like the RT patched debian you need to use multiple threads to optimize your software.
E.g. your idea to use software to de-bounce switches is not the best one: Our DIO and DI modules do have integrated STM processors as well as high level IO circuits which can di this task very well. You just need to set up de-bouncing in the PiCtory configuration. This is just one example of how you should aim your ideas: Use subsystems as much as possible. You do not have direct access to IOs like on a small embedded system. So you cannot use software to do the high speed stuff with a RevPi. PWM, counting encoders, etc. this is stuff which must be done by the subsystem.
I've written many programs using polling loops to picontrol and I can't really confirm your CPU usage numbers. But I must confess I never ever was even trying 10 ms loops as this doesn't really make deep sense on a RevPi. The IO cycles of the backplane bus PiBridge would not really support this speed on a medium size modular system and even when controlling things in motion like the valves in our water / oil tank demonstration for the exhibitions or the conveyor in the robotor demo from last SPS/Drives fair we do not need that high resolution to get sufficient results. A 50 ms loop time (100 ms reaction time) is sufficient to most applications if you can use high speed subsystems doing the "close to hw control" stuff.
First of all, yes there will be a possibility soon to call IOCTLs which let your task wait for a certain IO change. It will work like the current IOCTL used to monitor picontrol resets. You start the task which is doing the call and the call returns with the new value as soon as there is one. So this is close to interrupt style operation.
Then I think you need to think different in a multi tasking operation system device. It seems to me that your roots are coming from programming small embedded systems. With a complex system like the RT patched debian you need to use multiple threads to optimize your software.
E.g. your idea to use software to de-bounce switches is not the best one: Our DIO and DI modules do have integrated STM processors as well as high level IO circuits which can di this task very well. You just need to set up de-bouncing in the PiCtory configuration. This is just one example of how you should aim your ideas: Use subsystems as much as possible. You do not have direct access to IOs like on a small embedded system. So you cannot use software to do the high speed stuff with a RevPi. PWM, counting encoders, etc. this is stuff which must be done by the subsystem.
I've written many programs using polling loops to picontrol and I can't really confirm your CPU usage numbers. But I must confess I never ever was even trying 10 ms loops as this doesn't really make deep sense on a RevPi. The IO cycles of the backplane bus PiBridge would not really support this speed on a medium size modular system and even when controlling things in motion like the valves in our water / oil tank demonstration for the exhibitions or the conveyor in the robotor demo from last SPS/Drives fair we do not need that high resolution to get sufficient results. A 50 ms loop time (100 ms reaction time) is sufficient to most applications if you can use high speed subsystems doing the "close to hw control" stuff.
Unser RevPi Motto: Don't just claim it - make it!
Re: alternative to software polling to check variable changes?
Hi Volker,
thanks for the reply, I will wait for the WAIT signal from the new ioctl.
The debounce time is an example, a 100ms time is a human perceptible timescale for event delays (a visual change of any kind), so this time needs dealing with in software regardless of the hardware updates, by the way I agree that Pictory is the best place to set up a the debounce option but it does not save you from polling for changes at a decent interval.
The polling time is on top of any hardware polling you have underneath, so the polling time used by the picontrol driver, this is polling of polling -correct me if I am wrong-, some signalling from the first required polling among modules up to whoever needs it in software would be better.
The software I am using is multi-threaded and responsive but too many threads lead to context switching and waste of resources, race conditions etc, the revpi core has a single core by the way. Also there may be little point in using multiple threads to deal with hardware interactions that depend on each other and are by nature single threaded.
I would also suggest you change the lightswitch example loop with while(1) since it does take up 40% of the CPU.
Here is my test using the time tool on Linux (you can see it with top too), by running the loop for 30 secs:
Don't get me wrong, I think the revpi is a great product, these comments are for the sake of improvement.
Regards
Enrico
thanks for the reply, I will wait for the WAIT signal from the new ioctl.
The debounce time is an example, a 100ms time is a human perceptible timescale for event delays (a visual change of any kind), so this time needs dealing with in software regardless of the hardware updates, by the way I agree that Pictory is the best place to set up a the debounce option but it does not save you from polling for changes at a decent interval.
The polling time is on top of any hardware polling you have underneath, so the polling time used by the picontrol driver, this is polling of polling -correct me if I am wrong-, some signalling from the first required polling among modules up to whoever needs it in software would be better.
The software I am using is multi-threaded and responsive but too many threads lead to context switching and waste of resources, race conditions etc, the revpi core has a single core by the way. Also there may be little point in using multiple threads to deal with hardware interactions that depend on each other and are by nature single threaded.
I would also suggest you change the lightswitch example loop with while(1) since it does take up 40% of the CPU.
Here is my test using the time tool on Linux (you can see it with top too), by running the loop for 30 secs:
Code: Select all
$ sudo apt-get install time
$ /usr/bin/time -f '%Pcpu %Uu %Ss %er %MkB %C' ./lightswitch I_1_i03 O_5
./lightswitch is running waiting for switch 'I_1_i03'
42%cpu 5.46u 24.56s 71.10r 1880kB ./lightswitch I_1_i03 O_5
Regards
Enrico
Re: alternative to software polling to check variable changes?
Hi Enrico,
could you please give me a hint which "light switching" demo you are talking about? Is this hte "running light" demo in Python?
could you please give me a hint which "light switching" demo you are talking about? Is this hte "running light" demo in Python?
Unser RevPi Motto: Don't just claim it - make it!
Re: alternative to software polling to check variable changes?
Hi Volker,
On this page:
https://revolution.kunbus.de/tutorials/downloads/
Code Beispiel aus Video Tutorial Nr. 13
RevPi Beispiel Programmcode, der in unserem Video Tutorial 13 - PiTest Sourcecode verwendet wird.
The link: https://revolution.kunbus.de/download/1564/
It is called LightSwitch.c
Below the file with the 30 secs (cpu time) break-out. It is flagged 2016 and I don't know if it is obsolete by now, but it is a looping example in C, not Python.
Enrico
On this page:
https://revolution.kunbus.de/tutorials/downloads/
Code Beispiel aus Video Tutorial Nr. 13
RevPi Beispiel Programmcode, der in unserem Video Tutorial 13 - PiTest Sourcecode verwendet wird.
The link: https://revolution.kunbus.de/download/1564/
It is called LightSwitch.c
Below the file with the 30 secs (cpu time) break-out. It is flagged 2016 and I don't know if it is obsolete by now, but it is a looping example in C, not Python.
Enrico
Code: Select all
/*!
*
* Project: LightSwitch
*
* Demo source code for usage of piControl driver
*
* Copyright (C) 2016 : KUNBUS GmbH, Heerweg 15C, 73370 Denkendorf, Germany
*
* \file LightSwitch.c
*
* \brief Switch light if button is pressed.
*
*
*/
#include <piControlIf.h>
#include <piControl.h>
#include <string.h>
#include <stdio.h>
#include <time.h>
int main(int argc, char ** argv)
{
int i = 0;
int iLastInputValue = 0;
char *pchInput = NULL;
char *pchOutput = NULL;
// structures containing variable information: Name, Offset, Bit, Length
SPIVariable spiVariableIn = {"", 0, 0, 0};
SPIVariable spiVariableOut = {"", 0, 0, 0};
// structures containing variable value: Offset, Bit, Value
SPIValue sValueIn = {0, 0, 0};
SPIValue sValueOut = {0, 0, 0};
if(argc != 3)
{
printf("Usage: %s <PiCtory Input Pin> <PiCtory Output Pin>\n"
" i.e. %s Input_Pin_1 Output_Pin_1\n", argv[0], argv[0]);
return 0;
}
pchInput = argv[1]; // PiCtory input pin for Switch
pchOutput = argv[2]; // PiCtory output pin for Light
strncpy(spiVariableIn.strVarName, pchInput, sizeof(spiVariableIn.strVarName));
strncpy(spiVariableOut.strVarName, pchOutput, sizeof(spiVariableOut.strVarName));
i = piControlGetVariableInfo(&spiVariableIn); // PiBridge - get variable info
if(0 != i) // handle error
{
fprintf(stderr, "Error: piControlGetVariableInfo() returned %d for variable '%s' \n",
i, spiVariableIn.strVarName);
return -1;
}
i = piControlGetVariableInfo(&spiVariableOut); // PiBridge - get variable info
if(0 != i) // handle error
{
fprintf(stderr, "Error: piControlGetVariableInfo() returned %d for variable '%s' \n",
i, spiVariableOut.strVarName);
return -1;
}
sValueIn.i16uAddress = spiVariableIn.i16uAddress;
sValueIn.i8uBit = spiVariableIn.i8uBit;
sValueIn.i8uValue = 0;
sValueOut.i16uAddress = spiVariableOut.i16uAddress;
sValueOut.i8uBit = spiVariableOut.i8uBit;
sValueOut.i8uValue = 0;
printf("%s is running waiting for switch '%s' \n", argv[0], pchInput);
clock_t start, end;
double cpu_time_used;
start = clock();
while(1)
{
i = piControlGetBitValue(&sValueIn); // PiBridge - read input pin
if(0 != i) // handle error
{
fprintf(stderr, "Error: piControlGetBitValue() returned %d\n", i);
return -1;
}
if(iLastInputValue != sValueIn.i8uValue) // if button state changed
{ // show the change
printf("%-32s : %d \n", pchInput, sValueIn.i8uValue);
if(0 == sValueIn.i8uValue) // if button is released
{
if(1 == iLastInputValue) // and was pressed before
{ // switch light
sValueOut.i8uValue = ~sValueOut.i8uValue;
// PiBridge - set output pin
i = piControlSetBitValue(&sValueOut);
printf("%-32s : %s \n", pchOutput, sValueOut.i8uValue ? "On" : "Off");
if(0 != i)
{
fprintf(stderr, "Error: piControlSetBitValue() returned %d\n", i);
return -1;
}
}
}
}
iLastInputValue = sValueIn.i8uValue; // remember last input value
end = clock();
cpu_time_used = ((double) (end - start)) / CLOCKS_PER_SEC;
if(cpu_time_used > 30){
break;
}
}
return 0;
}
Re: alternative to software polling to check variable changes?
Oh ja,
das Teil kannte ich noch gar nicht im Detail... Das macht wirklich nicht Sinn im "real life" und ist echt nur als Stresstest für den revPi zu bewerten
Ja, natürlich würde man in real life applications hier pausieren in der loop. Je nachdem, welche Funktion der CPU am meisten Luft gibt, entweder mit einem Delay oder bei Nutzung der grafischen Oberflächen sogar über zyklische callbacks aus der GUI.
Da viele unserer Messeapplikationen auch eine GUI mit HDMI Monitor haben, gehe ich dort den letzteren Weg und bekomme so oft deutlich unter 20 % Systemlast mit pythonprogrammen, die als Task im call back durch die GUI zyklisch aufgerufen werden.
bei Systemlast bitte auch immer unterscheiden, von was wir reden. Leider nehmen viele Raspi User dort den Wert "load average" vom top Kommando. Wirklich aussagekräftig ist dieser Wert alleine aber nicht. Die Systemlast der CPU in % bekommt man durch Addition der Werte in der 3. Zeile von top (von system und user).
Zu picontrol:
Ja, es ist schon ein Polling, was da auf der PiBridge zwischen den IO Modulen und dem PA vom RevPi abläuft. Es wäre aber fatal, wenn Applikationen von diesem Polling aus über call backs eingeklinkt werden könnten. Dann wäre eine Zykluszeit nicht mehr von uns als Hersteller vorhersagbar und damit ein wichtiges Kriterium für Echtzeitsysteme nicht mehr gegeben. Auch Soft-SPSen würden mit so einer eventbasierten Verarbeitung nicht umgehen können. Es würde die regeln einer EN61131-3 basierten Software durchkreuzen.
Wir müssen daher als Hersteller hier 2 Welten zusammenführen: Die Welt der Steuerungen, die (noch) En61131-3 kompatibel sein muss und die Welt der embedded Programmierung, die mit ihren HW-Zugriffen in der Regel ganz anders vorgeht (IR-gesteuert, eventbasiert). Wir versuchen wie gesagt in picontrol in den kommenden Monaten einen Mechanismus einzuführen, der zumindest dem User überlässt, welchen Weg er wählen will. Aber auf dem Backplane Bus PiBridge wird es definitiv noch lange ein zyklischer Datenverkehr mit Polling bleiben. allein schon die Einbindung von Feldbussen erfordert dies zwingend, auch wenn man über den nutzen geteilter Meinung sein kann.
das Teil kannte ich noch gar nicht im Detail... Das macht wirklich nicht Sinn im "real life" und ist echt nur als Stresstest für den revPi zu bewerten
Ja, natürlich würde man in real life applications hier pausieren in der loop. Je nachdem, welche Funktion der CPU am meisten Luft gibt, entweder mit einem Delay oder bei Nutzung der grafischen Oberflächen sogar über zyklische callbacks aus der GUI.
Da viele unserer Messeapplikationen auch eine GUI mit HDMI Monitor haben, gehe ich dort den letzteren Weg und bekomme so oft deutlich unter 20 % Systemlast mit pythonprogrammen, die als Task im call back durch die GUI zyklisch aufgerufen werden.
bei Systemlast bitte auch immer unterscheiden, von was wir reden. Leider nehmen viele Raspi User dort den Wert "load average" vom top Kommando. Wirklich aussagekräftig ist dieser Wert alleine aber nicht. Die Systemlast der CPU in % bekommt man durch Addition der Werte in der 3. Zeile von top (von system und user).
Zu picontrol:
Ja, es ist schon ein Polling, was da auf der PiBridge zwischen den IO Modulen und dem PA vom RevPi abläuft. Es wäre aber fatal, wenn Applikationen von diesem Polling aus über call backs eingeklinkt werden könnten. Dann wäre eine Zykluszeit nicht mehr von uns als Hersteller vorhersagbar und damit ein wichtiges Kriterium für Echtzeitsysteme nicht mehr gegeben. Auch Soft-SPSen würden mit so einer eventbasierten Verarbeitung nicht umgehen können. Es würde die regeln einer EN61131-3 basierten Software durchkreuzen.
Wir müssen daher als Hersteller hier 2 Welten zusammenführen: Die Welt der Steuerungen, die (noch) En61131-3 kompatibel sein muss und die Welt der embedded Programmierung, die mit ihren HW-Zugriffen in der Regel ganz anders vorgeht (IR-gesteuert, eventbasiert). Wir versuchen wie gesagt in picontrol in den kommenden Monaten einen Mechanismus einzuführen, der zumindest dem User überlässt, welchen Weg er wählen will. Aber auf dem Backplane Bus PiBridge wird es definitiv noch lange ein zyklischer Datenverkehr mit Polling bleiben. allein schon die Einbindung von Feldbussen erfordert dies zwingend, auch wenn man über den nutzen geteilter Meinung sein kann.
Unser RevPi Motto: Don't just claim it - make it!
Re: alternative to software polling to check variable changes?
Sorry for all "non German speakers" but because of some German words in the last posting I've fallen back to my mother language. So here my answer again in English:
Oh Yes, you're right, I have never really studied this code snippet. It does not really make sense in areal life situation and you should take it as a simple example stressing the CPU of your revPi
You should of course add some kind of loop pause in real life applications. This could be either a simple delay or when using a GUI may be a cyclic call back from that GUI.
Many of our exhibit application do use a GUI with HDMI monitors. So I often used a cyclic GUI call back getting less than 20% system load with python programs running in their own task and being cyclically called by the GUI.
Please also sort things right when we are talking about system load: many users to take the "load average" from Linux top command to evaluate the system load. But this value alone doesn't say too much about the stress of your CPU. You only get the CPU load in % when adding "system" and "user" from the 3rd line of top output.
Referring picontrol:
Yes, you could call the cyclic data transfer between IO modules and the process image via PiBridge "polling". But the idea get user applications involved in this data-transfer (using callback etc.) would be fatal: We as manufacturer could no longer predict maximum cycle times and thus a critical requirement for real time systems would no longer be fulfilled. Also any "soft PLC" running on our system would not be able to deal with such event driven data manipulation. It would simply foil EN61131-3 rules.
It is our task as Vendor to get these 2 worlds together: The world of PLC which (up to now) needs to be compatible to EN61131-3 and the world of embedded programming using totally different ways to interact with HW (IR or event driven). As I've already stated we try to implement new methods into picontrol during the next months which will leave it up to the user which way of interacting with IO data he will go. But in matter of the back plane bus PiBridge this will definitely be a strict cyclical data transfer for long term future. This is a demand resulting from connection of field busses even if you might have a different opinion on how fieldbusses of the future should work.
Oh Yes, you're right, I have never really studied this code snippet. It does not really make sense in areal life situation and you should take it as a simple example stressing the CPU of your revPi
You should of course add some kind of loop pause in real life applications. This could be either a simple delay or when using a GUI may be a cyclic call back from that GUI.
Many of our exhibit application do use a GUI with HDMI monitors. So I often used a cyclic GUI call back getting less than 20% system load with python programs running in their own task and being cyclically called by the GUI.
Please also sort things right when we are talking about system load: many users to take the "load average" from Linux top command to evaluate the system load. But this value alone doesn't say too much about the stress of your CPU. You only get the CPU load in % when adding "system" and "user" from the 3rd line of top output.
Referring picontrol:
Yes, you could call the cyclic data transfer between IO modules and the process image via PiBridge "polling". But the idea get user applications involved in this data-transfer (using callback etc.) would be fatal: We as manufacturer could no longer predict maximum cycle times and thus a critical requirement for real time systems would no longer be fulfilled. Also any "soft PLC" running on our system would not be able to deal with such event driven data manipulation. It would simply foil EN61131-3 rules.
It is our task as Vendor to get these 2 worlds together: The world of PLC which (up to now) needs to be compatible to EN61131-3 and the world of embedded programming using totally different ways to interact with HW (IR or event driven). As I've already stated we try to implement new methods into picontrol during the next months which will leave it up to the user which way of interacting with IO data he will go. But in matter of the back plane bus PiBridge this will definitely be a strict cyclical data transfer for long term future. This is a demand resulting from connection of field busses even if you might have a different opinion on how fieldbusses of the future should work.
Unser RevPi Motto: Don't just claim it - make it!
Re: alternative to software polling to check variable changes?
Hallo Volker,
thanks for your reply -meinerseits ging es auf Deutsch auch aber nicht für die meisten-.
I don't dispute the choice of having a hardware polling layer, but I think the signalling you are introducing to notify the software layer when a change occurs on the hardware side is better than software polling, I'll wait for it.
Cheers
Enrico
thanks for your reply -meinerseits ging es auf Deutsch auch aber nicht für die meisten-.
I don't dispute the choice of having a hardware polling layer, but I think the signalling you are introducing to notify the software layer when a change occurs on the hardware side is better than software polling, I'll wait for it.
Cheers
Enrico