mirror of
https://github.com/fhem/fhem-mirror.git
synced 2025-04-15 16:19:11 +00:00
98_apptime:new timer concept
git-svn-id: https://svn.fhem.de/fhem/trunk@16327 2b470e98-0d58-463d-a4d8-8e2adae1ed80
This commit is contained in:
parent
efd6b49ee5
commit
3bc9150b97
@ -4,6 +4,8 @@
|
||||
# based on $Id$
|
||||
################################################################
|
||||
|
||||
# for use with fhem.pl 16214+ due to change in timers
|
||||
|
||||
#####################################################
|
||||
#
|
||||
package main;
|
||||
@ -15,10 +17,14 @@ use B qw(svref_2object);
|
||||
use vars qw(%defs); # FHEM device/button definitions
|
||||
use vars qw(%intAt);
|
||||
use vars qw($nextat);
|
||||
use vars qw(@intAtA); # Internal timer array (new!)
|
||||
use vars qw(%prioQueues);
|
||||
|
||||
sub apptime_getTiming($$$@);
|
||||
sub apptime_Initialize($);
|
||||
|
||||
use constant DEBUG_OUTPUT_INTATA => 0;
|
||||
|
||||
my $apptimeStatus;
|
||||
|
||||
sub apptime_Initialize($){
|
||||
@ -33,8 +39,6 @@ my $maxintatlen = 0;
|
||||
my $maxintatdone = 0;
|
||||
my $minTmrHandleTm = 1000000;
|
||||
my $maxTmrHandleTm = 0;
|
||||
my $minintatsorttm = 1000000;
|
||||
my $maxintatsorttm = 0;
|
||||
|
||||
my $totDly = 0;
|
||||
my $totCnt = 0;
|
||||
@ -42,84 +46,79 @@ my $totCnt = 0;
|
||||
sub HandleTimeout() {
|
||||
return undef if(!$nextat);
|
||||
|
||||
my $minCoverWait = 0.00; # 0.01 by Rudi, but it should be set only on systems that need it!?!
|
||||
my $minCoverExec = 2; # look ahead due to execution time of firing timers
|
||||
if (DEBUG_OUTPUT_INTATA) {
|
||||
my $ms = 0;
|
||||
my $n = int(@intAtA);
|
||||
my $j;
|
||||
for ($j=0; $j < ($n-1); $j++) {
|
||||
if (!defined($intAtA[$j])) {
|
||||
Log 0, "Error in intAtA, undefined element $j/$n\n";
|
||||
}
|
||||
elsif (!defined($intAtA[$j]->{TRIGGERTIME})) {
|
||||
Log 0, "Error in intAtA, undefined tim $j/$n\n";
|
||||
}
|
||||
next if ($intAtA[$j]->{TRIGGERTIME} <= $intAtA[$j+1]->{TRIGGERTIME});
|
||||
if (!$ms) {
|
||||
Log 0, "Error in intAtA, sortErr $j/$n\n";
|
||||
$ms = 1;
|
||||
}
|
||||
}
|
||||
$j = $n-1;
|
||||
if (!defined($intAtA[$j])) {
|
||||
Log 0, "Error in intAtA, undefined element $j/$n\n";
|
||||
}
|
||||
elsif (!defined($intAtA[$j]->{TRIGGERTIME})) {
|
||||
Log 0, "Error in intAtA, undefined tim $j/$n\n";
|
||||
}
|
||||
}
|
||||
|
||||
my $now = gettimeofday();
|
||||
my $dtnext = $nextat-$now;
|
||||
if($dtnext > $minCoverWait) { # need to cover min delay at least
|
||||
if($now < $nextat) {
|
||||
$selectTimestamp = $now;
|
||||
return $dtnext;
|
||||
return ($nextat-$now);
|
||||
}
|
||||
|
||||
my $handleStart = $now;
|
||||
|
||||
#############
|
||||
# Check the internal list.
|
||||
my @intAtKeys = keys(%intAt);
|
||||
|
||||
my @intAtSort = (sort {$intAt{$a}{TRIGGERTIME} <=>
|
||||
$intAt{$b}{TRIGGERTIME} }
|
||||
(grep {($intAt{$_}->{TRIGGERTIME}-$now) <= $minCoverExec}
|
||||
@intAtKeys)); # get the timers to execute due to timeout and sort ascending by time
|
||||
|
||||
my $intatsorttm = gettimeofday()-$now;
|
||||
|
||||
$intatlen = int(@intAtKeys);
|
||||
$intatlen = int(@intAtA);
|
||||
$maxintatlen = $intatlen if ($maxintatlen < $intatlen);
|
||||
|
||||
my $nd = 0;
|
||||
|
||||
my ($tim,$fn,$arg,$fnname,$shortarg,$cv);
|
||||
my ($fn,$arg,$fnname,$shortarg,$cv);
|
||||
$nextat = 0;
|
||||
foreach my $i (@intAtSort) {
|
||||
$i = "" if(!defined($i)); # Forum #40598
|
||||
next if(!$intAt{$i}); # deleted in the loop
|
||||
$tim = $intAt{$i}{TRIGGERTIME};
|
||||
$fn = $intAt{$i}{FN};
|
||||
if(!defined($fn) || !defined($tim)) { # clean up bad entries
|
||||
delete($intAt{$i});
|
||||
next;
|
||||
}
|
||||
if ($tim - gettimeofday() > $minCoverWait) {
|
||||
$nextat = $tim; # execution time not reached yet
|
||||
while(@intAtA) { # may be changed by timer execution !
|
||||
my $at = $intAtA[0];
|
||||
my $tim = $at->{TRIGGERTIME};
|
||||
if($tim && $tim > $now) {
|
||||
$nextat = $tim;
|
||||
last;
|
||||
}
|
||||
$arg = $intAt{$i}{ARG};
|
||||
delete $intAt{$at->{atNr}} if($at->{atNr}); # "handling" of old %intAt
|
||||
shift(@intAtA);
|
||||
|
||||
$fn = $at->{FN};
|
||||
$fnname = $fn;
|
||||
if (ref($fn) ne "") {
|
||||
$cv = svref_2object($fn);
|
||||
$fnname = $cv->GV->NAME;
|
||||
}
|
||||
$arg = $at->{ARG};
|
||||
$shortarg = (defined($arg)?$arg:"");
|
||||
$shortarg = "HASH_unnamed" if ( (ref($shortarg) eq "HASH")
|
||||
&& !defined($shortarg->{NAME}) );
|
||||
($shortarg,undef) = split(/:|;/,$shortarg,2); # for special long args with delim ;
|
||||
apptime_getTiming("global","tmr-".$fnname.";".$shortarg, $fn, $tim, $arg); # this can delete a timer and can add a timer not covered by the current loops TRIGGERTIME sorted list
|
||||
apptime_getTiming("global","tmr-".$fnname.";".$shortarg, $fn, $tim, $arg); # this can delete a timer and can add a timer
|
||||
$nd++;
|
||||
|
||||
delete($intAt{$i});
|
||||
}
|
||||
|
||||
$maxintatdone = $nd if ($maxintatdone < $nd);
|
||||
|
||||
$now = gettimeofday();
|
||||
|
||||
foreach my $i (keys(%intAt)) { #(keys(%intAt)) (@intAtKeys)
|
||||
$i = "" if(!defined($i)); # Forum #40598
|
||||
next if(!$intAt{$i}); # deleted in the loop
|
||||
$tim = $intAt{$i}{TRIGGERTIME};
|
||||
$nextat = $tim if ( defined($tim)
|
||||
&& ( !$nextat # find the next time to trigger
|
||||
|| ($nextat > $tim) ) );
|
||||
}
|
||||
|
||||
$intatsorttm += gettimeofday() - $now;
|
||||
$minintatsorttm = $intatsorttm if ($minintatsorttm > $intatsorttm);
|
||||
$maxintatsorttm = $intatsorttm if ($maxintatsorttm < $intatsorttm);
|
||||
|
||||
$now = gettimeofday();
|
||||
|
||||
if(%prioQueues) {
|
||||
my $nice = minNum(keys %prioQueues);
|
||||
my $entry = shift(@{$prioQueues{$nice}});
|
||||
@ -145,8 +144,7 @@ sub HandleTimeout() {
|
||||
|
||||
return undef if !$nextat;
|
||||
|
||||
$dtnext = $nextat-$now;
|
||||
return ($dtnext > $minCoverWait) ? $dtnext : $minCoverWait; # need to cover min delay at least
|
||||
return ($now < $nextat) ? ($nextat-$now) : 0;
|
||||
}
|
||||
sub CallFn(@) {
|
||||
my $d = shift;
|
||||
@ -228,16 +226,16 @@ sub apptime_CommandDispTiming($$@) {
|
||||
$sFld = "max" if (!$sFld);
|
||||
$top = "top" if (!$top);
|
||||
my %fld = (name=>0,function=>1,max=>2,count=>3,total=>4,average=>5,maxDly=>6,avgDly=>7,cont=>98,pause=>98,clear=>99,timer=>2,nice=>2);
|
||||
return "$sFld undefined field, use one of ".join(",",keys %fld)
|
||||
return "$sFld undefined field, use one of ".join(",",sort keys %fld)
|
||||
if(!defined $fld{$sFld});
|
||||
my @bmArr;
|
||||
my @a = map{"$defs{$_}:$_"} keys (%defs); # prepare mapping hash 2 name
|
||||
$_ =~ s/[HASH\(\)]//g foreach(@a);
|
||||
|
||||
if ($sFld eq "pause"){# no further collection of data, clear also
|
||||
if ($sFld eq "pause"){# no further collection of data, clear also
|
||||
$apptimeStatus = 0;#stop collecting data
|
||||
}
|
||||
elsif ($sFld eq "cont"){# no further collection of data, clear also
|
||||
elsif ($sFld eq "cont") {# further collection of data, clear also
|
||||
$apptimeStatus = 1;#continue collecting data
|
||||
}
|
||||
elsif ($sFld eq "timer"){
|
||||
@ -245,7 +243,7 @@ sub apptime_CommandDispTiming($$@) {
|
||||
$filter = defined($filter)?$filter:"";
|
||||
$filter = "\^tmr-.*".$filter if ($filter !~ /^\^tmr-/);
|
||||
}
|
||||
elsif ($sFld eq "nice"){
|
||||
elsif ($sFld eq "nice") {
|
||||
$sFld = "max";
|
||||
$filter = defined($filter)?$filter:"";
|
||||
$filter = "\^nice-.*".$filter if ($filter !~ /^\^nice-/);
|
||||
@ -259,8 +257,6 @@ sub apptime_CommandDispTiming($$@) {
|
||||
$totCnt = 0;
|
||||
$maxintatlen = 0;
|
||||
$maxintatdone = 0;
|
||||
$minintatsorttm = 1000000;
|
||||
$maxintatsorttm = 0;
|
||||
}
|
||||
elsif ($sFld =~ m/(pause|cont)/){
|
||||
}
|
||||
@ -304,7 +300,6 @@ sub apptime_CommandDispTiming($$@) {
|
||||
else {@bmArr = sort { $b->[$field] cmp $a->[$field] } @bmArr;}
|
||||
my $ret = sprintf("active-timers: %d; max-active timers: %d; max-timer-load: %d ",$intatlen,$maxintatlen,$maxintatdone);
|
||||
$ret .= sprintf("min-tmrHandlingTm: %0.1fms; max-tmrHandlingTm: %0.1fms; totAvgDly: %0.1fms\n",$minTmrHandleTm*1000,$maxTmrHandleTm*1000,($totCnt?$totDly/$totCnt*1000:0));
|
||||
$ret .= sprintf("min-timersortTm: %0.1fms; max-timersortTm: %0.1fms\n",$minintatsorttm*1000,$maxintatsorttm*1000);
|
||||
$ret .= ($apptimeStatus ? "" : "------ apptime PAUSED data collection ----------\n")
|
||||
.sprintf("\n %-40s %-35s %6s %8s %10s %8s %8s %8s %-15s %s",
|
||||
"name","function","max","count","total","average","maxDly","avgDly","TS Max call","param Max call");
|
||||
@ -370,7 +365,7 @@ sub apptime_CommandDispTiming($$@) {
|
||||
Continue data collection after pause.
|
||||
</p>
|
||||
</dd>
|
||||
<dt><code><kbd>apptime [count|funktion|average|clear|max|name|total] [all]</kbd></code></dt>
|
||||
<dt><code><kbd>apptime [count|function|average|clear|max|name|total] [all]</kbd></code></dt>
|
||||
<dd>
|
||||
<p>
|
||||
Display a table sorted by the field selected.
|
||||
|
Loading…
x
Reference in New Issue
Block a user