Schrift
Wiki:Tipp zum Debugging: use Data::Dumper; local $Data::Dumper::Useqq = 1; print Dumper \@var;
[thread]7123[/thread]

Performanceprobleme / Tuning von Socketoperationen

Leser: 1


<< |< 1 2 >| >> 11 Einträge, 2 Seiten
Echelon1010000
 2005-07-11 16:18
#56267 #56267
User since
2005-06-29
18 Artikel
BenutzerIn
[default_avatar]
Hi

Eine etwas allgemeine Frage, aber für mich dennoch von Interesse.
Ich hab ein Script das Daten auf einen Socket schreibt. Das passiert ganz normal mit "print $socket "Text";"
Die Antwort wird mit "getline($socket);" gelesen.

Ich suche nach einer Möglichkeit diesen Vorgang zu beschleunigen.

Hintergund ist der: Mein Programm liest Systemparameter ein und stellt sie auf einem LCD dar. Die Software die die eigentliche Ausgabe auf das LCD übernimmt wird über einen TCP Socket angesprochen.
Wenn ich nun die Daten die auf dem LCD erscheinen sollen verändere, etwa weil sich ein Wert geändert hat, kann ich sozusagen zugucken wie ein Wert nach dem anderen aktualisiert wird.

Ein anderes Programm, das ich hier herumliegen hab ist da wesentlich schneller. Dort akutalisert sich die Anzeige gewissermassen "sofort". Der Haken: Das andere Programm ist erstens in C geschrieben und zweitens zeigt es nicht die Daten auf dem LCD an die ich haben möchte. (Sonst muesste ich ja nicht mein eigenes Programm schreiben)

Ich weiss das ich mit perl nicht an die Ausführungsgeschwindigkeit von C herankomme, aber vielleicht gibts ja Möglichkeiten das Schreiben und Lesen mit dem Socket ein wenig zu beschleuinigen. Zur Zeit benötigt ein Schreib/Lesevorgang etwa 0.4 Sekunden, teils sogar 0.7 Sekunden. Das sieht erstens unschön aus und zweitens kann man da von einer Echtzeitanzeige wohl nicht sprechen...

Welche Möglichkeiten habe ich um diesen Vorgang ein wenig zu "tunen"?

Gruss, Echelon
weismat
 2005-07-11 18:25
#56268 #56268
User since
2003-08-18
142 Artikel
BenutzerIn
[default_avatar]
Hi,
Vor kurzem habe ich ein ähnliches Problem gehabt. Mein Programm liest von einem Socket Daten, formattiert die Daten in ein anderes Format und schreibt sie an dann an einen zweiten Socket. Das Ganze erfolgt mit Peaks von bis zu 600 Messages pro Sekunde während des Starts und zwischen 20-30 Messages pro Sekunde konstant während der Hauptschleife.
Diese Anforderungen habe ich durch die Verarbeitung mit 2 Threads und intelligentes Lesen in Blöcken von 4 kByte erreichen können.
Kannst Du die Verarbeitung bei Dir asynchron gestalten? D.h. kannst Du Schreiben und Lesen entkoppeln?
Du würdest dann alle Zeilen zuerst schreiben und nach dem Schreiben alles Lesen. Im besten Fall benutzt dann dabei recv statt getline und schneidest Dir dann selbst die Antworten in einzelne Zeilen zurecht.\n\n

<!--EDIT|weismat|1121091995-->
Echelon1010000
 2005-07-11 18:47
#56269 #56269
User since
2005-06-29
18 Artikel
BenutzerIn
[default_avatar]
Hi
Nein, das Lesen / Schreiben kann ich so direkt nicht entkoppeln. Abgesehen davon das ich mich mit Threads nicht wirklich auskenne Liest mein Programm die Daten nicht ein. (Ausser die Antworten vom Server) sondern holt sie selber aus den Systemdaten, die Daten werden also im Programm, bei jedem Schleifendurchlauf erzeugt.

Im wesentlichen funktioniert es so: (Pseudocode)
Code: (dl )
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
LOOP:
# hole daten
...
viel code der z.B. die Drehzahlen von Lüftern ausliest
...
# Daten aufs Display bringen
print $socket "Temperatur";
my $answer=werteantwortaus();
if ( $answer eq "error" ) { die "error" }

print $socket "Drehzal CPU Lüfter";
my $answer=werteantwortaus();
if ( $answer eq "error" ) { die "error" }

print $socket "Systemlast";
my $answer=werteantwortaus();
if ( $answer eq "error" ) { die "error" }

sleep (10);
goto LOOP;


Das ganze besteht aus 11 Modulen die jeweils eine Sorte Daten einlesen und so (ähnlich*) wie oben auf das Display bringen. Die Module sind unter anderem für das Auslesen von Temperatur, CPU Last, Drehzahlen, Datenrate Netzwerk, Lastdiagramm und Speichernutzung zuständig und werden vom Hauptprogramm aus geforked.

IMO würde entkoppeln auch wenig bringen. Es ist egal wie schnell ich die Daten lese (geht ruckzuck, keine Verzögerungen), ich muss die Daten schneller schreiben. Ich würde ja sonst nur einen Zwischenspeicher vollschreiben der dann irgendwann überläuft. Im Wesentlichen geht es mir um das Lastdiagramm.
Dieses besteht aus 20 vertikalen Balken die die CPU Last (loadavg1) anzeigen. Alle 10 Sekunden wird das Diagramm aktualisiert, jeder Balken steht also für 10 Sekunden.

Wenn das Diagramm nun aktualisiert wird kann ich zugucken wie der neue Balken am Ende eigefügt wird und die andern alle eine Position nach rechts wandern. Diese 20 Operationen (jeweils Befehl schreiben und Antwort abholen) dauert fast 10 Sekunden.

Das ist mir zu lang und ich suche halt nach einer Möglichkeit diesen Vorgang zu beschleunigen. Ich stell auch gern den Code zu verfügung, allerdings wäre das zu viel für das Forum, das muesste ich dann via Mail machen oder so. Sind fast 70KBytes .pl Dateien. Einzelne Ausschnitte sofern gewünscht stelle ich gern ein. (Welche?)

Gruss, Echelon

*Tatsächlich befinden sich die Befehle um auf das Display zu schreiben in einer eigenen sub so das ich von jedem Modul aus darauf zugreifen kann. Statt jedesmal "print $socket "Blah"; reicht dann der Aufrug "lcdprint". In dieser sub befindet sich dann auch jeweils die Fehlerauswertung.
weismat
 2005-07-11 19:36
#56270 #56270
User since
2003-08-18
142 Artikel
BenutzerIn
[default_avatar]
Was ich meinte:
Code: (dl )
1
2
3
4
print $socket "Temperatur";
print $socket "Drehzal CPU Lüfter";
my $answer=werteantwortaus();
my $answer=werteantwortaus();

Je nachdem, wie das andere Programm funktioniert, wird das ganze so viel schneller ablaufen.
Echelon1010000
 2005-07-11 19:59
#56271 #56271
User since
2005-06-29
18 Artikel
BenutzerIn
[default_avatar]
Hi

Das funktioniert leider nicht, wenn ich die Antworten nicht annährend sofort hole wird mich das Gegenprogramm disconnecten. (3 Meldungen dürfen maximal in der Ausgabewarteschlange liegen) Ausserdem benötige ich die Antowrten zwecks Fehlerauswertung. Da die Antwort nur aus "success" oder "huh?" besteht kann ich sie dann nicht mehr zuordnen wenn ich sie später erst hole. Danke trotzdem...

Gruss, Echelon
weismat
 2005-07-11 20:25
#56272 #56272
User since
2003-08-18
142 Artikel
BenutzerIn
[default_avatar]
Dann würde ich trotzdem immer Blöcke von 3 Messages schicken...Ich glaube, daß Perl bei dieser Art von Verarbeitung ähnlich schnell wie C ist, da die gleichen System-Bibliotheken wie in C aufgerufen werden. Hast Du den Quellcode für das C Programm?\n\n

<!--EDIT|weismat|1121099163-->
Echelon1010000
 2005-07-11 20:53
#56273 #56273
User since
2005-06-29
18 Artikel
BenutzerIn
[default_avatar]
Hi

Ja, den Quellcode habe ich, ist ein Opensource Programm. Es handelt sich dabei um ein Beispielprogramm zum lcdproc-Projekt. Kann ich dir mailen oder du lädst es von der HP http://lcdproc.omnipotent.net.  Ich hab ihn mir auch schon angesehen, allerdings sind meine C Kenntnisse noch  rudimentär. Selber schreiben könnte ich sowas nicht. (Sonst hätte ich wahrscheinlich C für mein Projekt genommen...)

Im Prinzip macht es das gleiche wie mein Perlprogramm. Ich hab, ohne den Code zu kennen fast das gleiche programmiert. Die Entwickler gehen auch so vor: Schreiben/Lesen Schreiben/Lesen.  

Warum das bei mir langsamer ist hab ich mir bis jetzt dadurch erklärt das perl eben keine kompilierte Sprache ist. Deswegen dachte ich das es evtl Kniffe gibt die ich noch nicht kenne oder eben effektivere Methoden mit dem Socket zu arbeiten...

Das mit dem mehrere Nachrichten zu verschicken funktioniert übrigens nicht, die Module sind geforked, ich hab nicht wirklich die Kontrolle darüber wann ein Modul eine Nachricht schickt. Die Antworten auswerten haut dann auch nicht hin und eine Zuordnung könnte ich dann ganz vergessen. Davon ab: Der Versuch scheitert weil er das mit den drei Nachrichten wohl nicht immer einhält. Manchmal schmeisst er mich schon aus der Leitung wenn ich die zweite Nachricht schicke, manchmal kann ich 4 oder mehr Nachrichten absetzen. Das hängt wohl auch damit zusammen das er von Zeit zu Zeit selber Nachrichten auf die Ausgabewarteschlange setzt, die wollen auch abgeholt werden.

Gruss, Echelon
weismat
 2005-07-11 23:33
#56274 #56274
User since
2003-08-18
142 Artikel
BenutzerIn
[default_avatar]
Ich habe mir das kurz angeschaut und festgestellt, daß alle Beispiele in Perl sind, hast Du Dir das clients/examples verzeichnis mal angeschaut?
esskar
 2005-07-12 00:31
#56275 #56275
User since
2003-08-04
7321 Artikel
ModeratorIn

user image
arbeitest du mit IO::Select, damit du weißt, wann du lesen und schreiben darfst?
Echelon1010000
 2005-07-12 00:45
#56276 #56276
User since
2005-06-29
18 Artikel
BenutzerIn
[default_avatar]
Hi

Ja, hab ich, aber da ist kein Realtime Client dabei. Die Beispielprogramme stellen alle irgendwie Zehlen dar, jedoch kein Diagramm. Der Client der das loaddiagramm darstellt ist unter clients/lcdproc zu finden.

Die Perlclients zeigen alle diverse Daten, aber keiner in irgendeiner Form eine Art diagramm. (Fpür Temperatur gibts auch keinen) Abgesehen davon laufen nicht alle Clients unter FreeBSD und ich hab grad kein Linux zum testen. Ich mein, es gibt Leute die lassen eine Winamp/mplayer/xmms Visualisierung darüber laufen, also muss das irgendwie gehen... Nur wie?

Gruss, Echelon
<< |< 1 2 >| >> 11 Einträge, 2 Seiten



View all threads created 2005-07-11 16:18.