Entwickler-Ecke
Delphi Language (Object-Pascal) / CLX - Thread zu langsam
bbfan - Di 21.08.07 11:08
Titel: Thread zu langsam
Hallo Leute!
Ich weiss nicht mehr was ich noch machen soll, aber mein Thread ist tierisch langsam.
Folgendes Tuning habe ich bereits gemacht.
Hauptappl. Prozessorzeit erhöht:
Delphi-Quelltext
1:
| SetPriorityClass(GetCurrentProcess, HIGH_PRIORITY_CLASS); |
Thread Priority erhöht:
Delphi-Quelltext
1:
| SetThreadPriority(Handle, THREAD_PRIORITY_TIME_CRITICAL); |
Mal benötigt die CPU 10 msec für die "execute" Bereich, dann wieder bis 200msec. Im Schnitt immer so um die 90msec.
Hier der gesamte Thread:
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23:
| new(rthreadSpeed); rthreadSpeed^.total_rounds:=0; rthreadSpeed^.msec:=0; while (abbruch.Status=false) do begin if getThreadPriority(handle)<>THREAD_PRIORITY_TIME_CRITICAL then SetThreadPriority(Handle, THREAD_PRIORITY_TIME_CRITICAL); time_begin:=time; CapGrabSingleFrameBMP(bmp_live); add2MemStream(PIC_PATH + GBL_event_id+'\'+generateUniqueFileName(USER_ID+'_stream.jpg')); DecodeTime(time-time_begin, Hour, Min, Sec, MSec); rthreadSpeed^.msec:=rthreadSpeed^.msec + ((Sec*1000) + MSec); rthreadSpeed^.total_rounds := rthreadSpeed^.total_rounds + 1; rthreadSpeed^.last_msec := ((Min * 60 * 1000) + (Sec * 1000) + MSec); k:=r_speed_msec - rthreadSpeed^.last_msec; if k > 0 then begin SetThreadPriority(Handle, THREAD_PRIORITY_NORMAL); sleep(round(k)); end; end; bmp_live.free; r_err.free; temp_bmp.free; |
Gausi - Di 21.08.07 11:39
Die Priorität derart zu erhöhen ist iirc eine sehr ungute Idee. Was macht denn dein Thread genau? Wie und wieoft wird mit dem Hauptthread synchronisiert (denn das dauert recht lange)?
Was machen die Funktionen, die du da aufrufst? Eine Bremse könnte evtl. der MemStream sein. Wenn das ein Memorystream ist, und der "voll" ist, dann muss ggf. komplett im Speicher umkopiert werden.
bbfan - Di 21.08.07 13:18
Ich habe festgestellt, dass diese Funktion "CapGrabSingleFrameBMP(bmp_live);" die CPU Zeit frisst.
Diese Funktion grabed ein WebCam Bild in ein TBitmap.
Hier stellte ich fest, dass die Geschwindigkeit auch abhängig von der Hardware ist. Ich habe 2 Webcams. Arbeite ich mit der einen, so können max. 6 Bilder pro Sekunde gegerabt werden. Mit der 2. Wecam schaffe ich 18 Bilder.
Es scheint hier also auch die Hardware eine Rolle zu spielen.
Trozdem benötigt das eine Grabben mal 10msec und dann wieder 100msec. Das verstehe ich nicht.
Ich führe es darauf zurück, dass der Thread mal viel CPU Zeit bekommt, mal weniger.
Eine Sync. wird nicht durchgeführt, da diese hier nicht gebraucht wird.
Ich arbeite nicht mit MemoStream... Ich habe ein TList in der ich TJpegImage Records reinschiebe (Buffer). Der Buffer wird regelmäßig weggeschrieben. Ein Volllaufen des Speichers ist ausgeschlossen.
Ich habe aus der execute Methode alle andere Prodceduren mal ausgeklammert und es ist eindeutig das Grabben des Frame von der WebCam, was die Zeit frist. Und zwar extrem unterschiedlich. Mal dauert es 10msec, dann wieder 100msec. Faktor 10!!!
Die Thread Priority spielt auch eine Rolle. Bei geringer Priorität dauert es noch länge als bei hoher.
Lossy eX - Di 21.08.07 13:49
Wie Gausi schon sagte ist das Verändern der Prioritäten nur mit Vorsicht zu genießen. Bzw ein Setzen der Prio auf Kritisch hat dort nichts zu suchen. Denn das Einzige was du damit erreichst ist die Stabilität des Systems zu gefährden. Normal sollten nur Kernelkomponentem etc. diese Priorität bekommen. Denn du blockierst damit unter Umständen auch wichtige Teile des Betriebssystems die teilweise selber auch nur auf Hoch laufen. Und wie du ja festgestellt hast bringt es gar nichts.
Aber du ließt von einer Webcam. Die sind externe Hardware und müssen über USB angesprochen werden. Wie du ja selber gesehen hast ist diese auch nicht immer gleich schnell. Es kommt also auch auf die in der Hardware verbauten Teile an und wie viel Traffic sonst noch auf dem USB liegt.
Außerdem speicherst du JPEGs ab, oder? Das Komprimieren eines JPEGs dauert je nach Größe auch einiges an Zeit. Denn das Lesen eines 800x600 großen JPEGs dauert mit der Implementation von Delphi schon knapp 150-200ms.
Bzw wie misst du die Zeit die vergangen ist? Mit GetTickCount? Wenn ja würde ich eher auf den PerformanceCounter setzen. Der kommt direkt vom Prozessor und ist damit wesentlich zuverlässiger und genauer. Siehe QueryPerformanceFrequency und QueryPerformanceCounter.
bbfan - Mi 22.08.07 08:48
Danke für deine Hinweise:
Also die Prozesszeit ermittele ich so:
Delphi-Quelltext
1: 2: 3: 4: 5:
| time_begin:=time; CapGrabSingleFrameBMP(bmp_live); add2MemStream(PIC_PATH + GBL_event_id+'\'+generateUniqueFileName(USER_ID+'_stream.jpg')); DecodeTime(time-time_begin, Hour, Min, Sec, MSec); rthreadSpeed^.process_time := ((Min * 60 * 1000) + (Sec * 1000) + MSec); |
Falscher Weg?
Quasi 2 Zeitmessung über time() und dann subtrahieren...
OlafSt - Mi 22.08.07 12:29
Ah, USB - das erklärt einiges.
USB ist kein "direkter" Bus. Es ist ein reiner Master-Slave-Bus. Das heißt: Jedwede Transaktion, die über USB läuft, muß vom Master angestoßen werden. Jede, ohne Ausnahme. Das heißt, selbst wenn deine Webcam ein Bild fertig aufgenommen hat, muß der Master erst fragen: "Hast du was für mich ?".
Diese Master-Abfragen finden prinzipbedingt alle 100ms statt, IIRC. Dein Thread trifft nun manchmal genau den richtigen Zeitpunkt - manchmal auch nicht. So kommen die seltsamen Zeitunterschiede zustande. Daran ist nichts zu rütteln, auch höchstmögliche Thread-Prios werden nichts helfen.
Die interne Uhr dann für Laufzeitermittlungen zu verwenden, ist auch so eine Sache... Ich persönlich benutze aus der JCL die TJCLCounter - die arbeiten Nanosekunden-Genau (RDTSC usw).
bbfan - Fr 24.08.07 08:17
Ok Vielen Dank für eurer Hilfe und Informationen.
Entwickler-Ecke.de based on phpBB
Copyright 2002 - 2011 by Tino Teuber, Copyright 2011 - 2025 by Christian Stelzmann Alle Rechte vorbehalten.
Alle Beiträge stammen von dritten Personen und dürfen geltendes Recht nicht verletzen.
Entwickler-Ecke und die zugehörigen Webseiten distanzieren sich ausdrücklich von Fremdinhalten jeglicher Art!