Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Netzwerke (https://www.delphipraxis.net/14-netzwerke/)
-   -   Delphi Indy -IdTcpServer führt zu 100% CPU -Last (https://www.delphipraxis.net/12026-indy-idtcpserver-fuehrt-zu-100-cpu-last.html)

DataCool 18. Nov 2003 23:49


Indy -IdTcpServer führt zu 100% CPU -Last
 
Hi Leute,

ich bin's mal wieder mit einer Indy-Frage, ich kämpfe jetzt schon sehr lange mit den Indy-Komponenten, aber manchmal könnte ich das Blocking Sockets verfluchen. Warum haben die sich dafür entschieden ?

Aufgabe:
Bildübertragung eines Webcam-Bilds so gut und schnell wie möglich.

Problem:
Im Moment verwende ich produktiv gerade ein eigenes Protokoll das noch sehr viel Overhead hat.
Aber 4 Leute können problemlos mein Bild betrachten.
Jetzt habe ich mein Protokoll wirklich auf das wichtigste beschränkt die Bildübertragung.

Code Beispiel Server :
Code:
Var ms  : TMemoryStream;
      ImgWrapper : TImageWrapper;
      sCmd : String;
begin
   // Speicher zur Bildablage im Stream erzeugen
   ms := TMemoryStream.Create;
   // KLasse zum Abgreifen des Video-Bild erzeugen
   imgWrapper := TImageWrapper.Create(AThread,frmMain.Video);
   try
      imgWrapper.FileSys := bFileSys;
      imgWrapper.Kompression := Einstell.Compression; // Bildkompression setzen
      // Solange eine Socket-Verbindung besteht jetzt das Bild zum Kunden übertragen
      While (AThread.Connection.Connected) do begin
         // MemoryStream leeren
         ms.clear;
         // aktuelles Bild jetzt laden/abgreifen
         if imgWrapper.loadImage then begin
            // Geladenes Bild in Strean schreiben
            imgWrapper.WriteToStream(ms);
            // Bildspeicherposition auf den Anfang setzen
            ms.Position := 0;
            // Bild einfach in den Buffer schreiben und abschicken
            // durch die entsprechenden Parameter in WriteStream,
            // steht in den ersten vier Bytes des Streams die Stream Grösse
            try
               AThread.Connection.OpenWriteBuffer;
               AThread.Connection.WriteStream(ms,true,true);
               AThread.Connection.CloseWriteBuffer;
            except
               logf.log('Versuche Write Buffer zu canceln',1);
               //AThread.Connection.CancelWriteBuffer;
               AThread.Connection.ClearWriteBuffer;
               //AThread.Connection.DisconnectSocket;
            end;
         end
         else begin
            // es konnte kein Bild geladen werden, es wird jetzt der leere Stream zum Client geschickt
            // der überprüft anhand der Streamgrösse ob er darauf reagiert, so wird der normale
            // Befehlsablauf nicht unterbrochen
            AThread.Connection.OpenWriteBuffer;
            try
               AThread.Connection.WriteStream(ms,true,true);
               AThread.Connection.CloseWriteBuffer;
            except
               //AThread.Connection.CancelWriteBuffer;
               AThread.Connection.ClearWriteBuffer;
            end;
            logf.log('Send empty stream size 0',1);
         end;
      end;
   finally
      // Speicher wieder freigeben
      ms.Clear;
      FreeAndNil(ms);
      FreeAndNil(ImgWrapper);
   end;
Code Bsp. Client :
Code:
// die Procedure StreamNow wird innerhalb des VideoStreamThread immer wieder aufgerufen
procedure TVideoStreamThread.StreamNow;
begin
   // Speicher leeren
   ms.Clear; //     
   try
      if (TcpCon.Connected) and (not Terminated) then begin
         try
            TcpCon.ReadStream(ms);
         except
            ms.clear;
         end;
         if ms.Size > 0 then begin
            // Stream Position auf null, damit vom Anfang gelesen wird
            ms.Position := 0;
            jpg.LoadFromStream(ms);
            // Haben wir ein gültiges Jpg
            if not jpg.Empty then begin
               aktJpg := jpg;
               // Jpg zeichnen
               Synchronize(PaintImage);
            end;
         end;
      end;
   finally
      // Memory-Stream leeren
      ms.clear;
   end;
end;
Wie Ihr seht beschränkte ich mich jetzt auf die reine Bildübertragung, das Problem dabei ist, das das Bild zwar super schnell und super flüssig wird, aber ab dem dritten User beim Server die CPU Last auf 100% steigt und ich nicht nachvollziehen kann warum.
In meinen Logfile steht kein einziger Fehler von irgenteinem Thread, kann es sein das diese intensiven Threads für Windows bzw. Indy zuviel sind ?

Jeder Kommentar hilft vielleicht weiter, sitze schon etwas länger darüber und komme jetzt gerade nicht weiter.
Und das ist echt frustierend bin schon am überlegen, ob ich das ganze Projekt auf die ICS-Komponenten umschreibe, aber das würde etwas dauern und ich habe mit denen auch noch keinerlei Erfahrung.

Was sagt Ihr ?

Danke Data

DataCool 19. Nov 2003 14:27

Re: Indy -IdTcpServer führt zu 100% CPU -Last
 
Fehler gefunden ! Dank an Luckie :hello:

Kleiner Tipp für alle die mal mit ähnlichen Problemen kämpfen sollten :

Auch Festplattenzugriffe(egal ob Lesen oder Schreiben) innerhalb eines Threads sollten unbedingt syncronisiert werden :warn:

Das war in meiner ImageWrapper-Klasse in der Methode LoadImage nicht der Fall.

Gruß Data


Alle Zeitangaben in WEZ +1. Es ist jetzt 12:00 Uhr.

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz