Hi
Danke für den Tip, auf die Idee bin ich noch nicht gekommen. Allerdings hab ich ein paar Zeitmessungen gemacht. Das Ergebnis sieht so aus:
Code:
lo: 1 net: 0.0015110969543457 calc: 0.000602960586547852 set: 0.55401611328125 totl 0.556481838226318
lo: 2 net: 0.000720024108886719 calc: 0.000113964080810547 set: 0.519311904907227 totl 0.520215034484863
lo: 3 net: 0.000390052795410156 calc: 0.000117063522338867 set: 0.399712085723877 totl 0.400292158126831
lo: 4 net: 0.00039219856262207 calc: 0.000117063522338867 set: 1.75984597206116 totl 1.76042795181274
lo: 5 net: 0.000391006469726562 calc: 0.000115871429443359 set: 0.179728984832764 totl 0.180307149887085
lo: 6 net: 0.000388860702514648 calc: 0.000118017196655273 set: 0.319777965545654 totl 0.320359230041504
lo: 7 net: 0.000391006469726562 calc: 0.000118017196655273 set: 0.159677982330322 totl 0.16025710105896
lo: 8 net: 0.000369071960449219 calc: 0.000111103057861328 set: 0.259702920913696 totl 0.260254859924316
lo: 9 net: 0.000393867492675781 calc: 0.000118017196655273 set: 0.189710140228271 totl 0.19028902053833
lo: 10 net: 0.000392913818359375 calc: 0.000118017196655273 set: 0.289711952209473 totl 0.290292978286743
lo: 11 net: 0.000387907028198242 calc: 0.000116109848022461 set: 1.65973281860352 totl 1.66030883789062
lo: 12 net: 0.000427007675170898 calc: 0.000120878219604492 set: 0.409691095352173 totl 0.410310029983521
lo: 13 net: 0.00038909912109375 calc: 0.000116825103759766 set: 0.39968204498291 totl 0.400264024734497
lo: 14 net: 0.000479936599731445 calc: 0.000117063522338867 set: 0.429741144180298 totl 0.430413961410522
lo: 15 net: 0.000422954559326172 calc: 0.000132083892822266 set: 0.399968862533569 totl 0.400609016418457
lo: 16 net: 0.000435113906860352 calc: 0.000121116638183594 set: 0.389736890792847 totl 0.390370845794678
lo: 17 net: 0.00038909912109375 calc: 0.000115156173706055 set: 1.759850025177 totl 1.76042485237122
lo: 18 net: 0.000390052795410156 calc: 0.000114917755126953 set: 0.189707040786743 totl 0.190285921096802
lo: 19 net: 0.000406980514526367 calc: 0.000117063522338867 set: 0.329722166061401 totl 0.330317974090576
lo: 20 net: 0.000387907028198242 calc: 0.000112056732177734 set: 0.159653902053833 totl 0.160226821899414
Hierbei:
lo - Schleifendurchlauf (Nummer)
net - Abfrage der Daten über die Funktion
calc - Umrechnen der Daten von Byte nach KByte
set - Weiterleiten der Daten an lcdproc
totl - Gesamtdurchlauf
Die Differenz zwischen Durchlauf und der Summe der Einzelwerte kommt zustande weil ich die Ausgabe auf dem Bildschirm und den bedingten Rücksprung zum Schleifenbeginn vernachlässige.
Mein Testprogramm sieht so aus:
Code:
my $pid=fork();
if ( $pid == 0 )
{
debug ("Child successfully started!");
my $blubb=0;
LOOP:
my $start=time();
# Grab networkstats
$bnet=time();
$network = get_network_io_stats_diff;
$anet=time();
# calculate and display values for $statgrabif1
if ( $statgrabif1 ne "none")
{
$bcalc=time();
my $if1rx=$network->rx($grabstatif1);
my $if1tx=$network->tx($grabstatif1);
my $if1krx=sprintf("%.2f",$if1rx/1024);
my $if1ktx=sprintf("%.2f",$if1tx/1024);
$acalc=time();
$bset=time();
setstring ("statgrab-if1","statgrab-if1-rx-v",4,2,$if1krx);
setstring ("statgrab-if1","statgrab-if1-tx-v",14,2,$if1ktx);
setstring ("statgrab-net","statgrab-net-if1-rx-v",6,2,$if1krx);
setstring ("statgrab-net","statgrab-net-if1-tx-v",14,2,$if1ktx);
$aset=time();
}
$blubb++;
if ( $blubb > 20 ) { goto ENDSTATGRABNET; }
$end=time();
$net=$anet-$bnet;
$calc=$acalc-$bcalc;
$set=$aset-$bset;
$total=$end-$start;
print "lo: $blubb ";
print "net: $net ";
print "calc: $calc ";
print "set: $set ";
print "totl $total ";
print "\n";
sleep (1);
goto LOOP;
ENDSTATGRABNET:
exit 0
}
Dazu noch die Funktion "setstring" mit der die Daten an lcdproc weitergeleitet werden:
Code:
sub setstring
{
# sets x,y and value of a string-type widget
# setstring ( $screen,$name,$x,$y,$value );
my $screen=$_[0];
my $name=$_[1];
my $x=$_[2];
my $y=$_[3];
my $value=$_[4];
print $socket "widget_set $screen $name $x $y $value";
debug ( "widget_set $screen $name $x $y $value");
suck();
return 1;
}
Zu guter Letzt:
Die Funktion suck() Diese nimmt Nachrichten vom Daemon entgegen und wertet sie aus. Das sind einmal Nachrichten über Erfolg/Mißerfolg eines Befehls, andererseits Informationen darüber welcher Screen gerade angezeigt wird und wie lange.
Code:
sub suck {
# fetch answer from server and process it
FETCHME:
my $answer=<$socket>;
# if we recieve one of this ridicoulous "listen" messages
# it will disturb the communication with the server so
# we throw it away and refetch the message from the server
# Note that a screen with "listen" or "ignore" in its name
# may result in a endless loop...
if (index($answer,"listen")>=0)
{
debug("Discarded silly listen-message");
goto FETCHME;
}
if (index($answer,"ignore")>=0)
{
debug ("Discarded silly ignore-messages");
goto FETCHME;
}
if (index($answer,"huh?")>=0)
# Something's going wrong, check this out
{
debug("error recieved: $answer");
if (index($answer,"exists")>=0)
{
die "Fatal error while registering screen. Server said: $answer\n";
}
}
if (index($answer,"success")>=0)
{
debug ("success");
}
return 1
}
Ich bin also soweit das ich weiß wo mein Zeitproblem herkommt. Es ist die Weitergabe der Daten an lcdproc. Während die anderen Teile nur wenige µs brauchen (was man vernachlässigen könnte) dauert die Übergabe an den Daemon im Schnitt eine halbe Sekunde. Teilweise sind auch Aussetzer von 1.5 Sekunden und mehr dabei.
Zu deinem Vorschlag:
Ich werde das mal antesten. Auf die Sekunde bin ich aus zwei Gründen gekommen:
Erstens hatte ich die irrige Annahme das mein Schleifendurchlauf nur sehr sehr wenig Zeit in Anspruch nimmt. Entsprechend dachte ich, ich könnte die Schleife einmal pro Sekunde laufen lassen und hätte dann automatisch, ohne großartig rumzurechnen die KB/s.
Zweitens will ich versuchen die Daten möglichst zeitnah aufs Display zu bringen. Das heißt, der Balken der den Durchsatz anzeigt soll mehr oder weniger in Echtzeit auf Aktivitäten im Netz reagieren. Daher habe ich versucht die Abfragerate möglichst weit hochzuschrauben. Den Overhead der dabei entsteht ist vernachlässigbar: Es wird kaum Last erzeugt und der Client kommuniziert auf lo0. Prinzipiell hätte ich nichts dagegen die Werte noch öfter abzuholen. Das Display wird von lcdproc 8 mal pro Sekunde aktualisiert, ich könnte also eine Echtzeitanzeige bekommen.
Ich sehe im Moment zwei Wege:
Möglichkeit 1:
Datenabfrage und Weiterleitung abkoppeln. Dann kann exakt einmal/Sekunde (oder öfter) die Datenauswertung erfolgen und die Funktion die dafür zuständig ist die Daten ans Display weiterzugeben kann "in Ruhe" die Daten so schnell hochschieben wie sie eben kann.
Möglichkeit 2:
Die Funktion die die Daten an lcdproc gibt schneller machen oder dafür sorgen das das Programm weiterläuft während die Daten noch hochgeschickt werden.
Ich weiß noch nicht wie ich das am sinnvollsten anstelle. Wahrscheinlich werde ich eine Mischung aus deinem Vorschlag und der zweiten Möglichkeit versuchen. Also die Sub schneller machen und die Zeit variabel messen...
Gruß, Echelon
Nachtrag:
Das fiel mir gerade ein: Ich hab das Teil gewissermaßen unter idealen Bedingungen getestet. Eigentlich sind da noch mehr Clients die ebenfalls Daten an lcdproc ausliefern sollen. Das Zeitproblem könnte sich dadurch noch vergrößern, ich weiß nicht wie lcdproc verschiedene parallele Anfragen beantwortet/verarbeitet.