ReadFile(.) - Zugriff auf die RS232 über Windows-API. Performance?

OP #1205438
Hallo,

ich greife mit Hilfe eines Workerthreads auf die serielle Schnittstelle 
zu. Dabei erfolgt die Kommunikation mit dem Hauptprogramm über jeweils 
eine separate queue<char>. Der Einfachheit halber habe ich mit ReadFile 
jedes Byte separat abgeholt und in die Queue eingefügt. Funktioniert 
auch, aber ich hab das Gefühl, die Performance ist da ganz schön 
bescheiden. Leider kann ich an keinem Pin wackeln und so am Oszi 
nachmessen, was da Phase ist.

Vielleicht kann mir jemand von euch eine Hausnummer nennen, wie lange so 
ein ReadFile-Aufruf durchschnittlich dauert und ob es besserer Stil ist, 
immer alle Bytes aus dem Rx-Puffer mit einem Aufruf zu lesen?
Hallo
Dein 'Pin' ist der Performance-Monitor.
Deine Übertragung dauert : [Zeit] = [Anzahl-Bytes]/[baud]*10
Die Zehn komt von 8N1.

Sicherlich ist es Performanter ganze Blöcke zu lesen.
Aber du wirst es weder merken noch messen können.
Ich habe einen blockierenden Aufruf verwendet. Er kehrt bei mir erst 
zurück wenn entweder :
 - Bestimmte Anzahl Bytes angekommen sind.  oder
 - Ein bestimmtes Zeichen angekommen ist.   oder
 - Ein Timeout aufgetreten ist.

viel Spass beim Rechnen!
OP
Hallo, deine Rechnung ist soweit schon klar. Ich habe aber die 
Befürchtung, dass der Löwenanteil vom Windows selbst verschlungen wird 
und ontop auf die reine Übertragungszeit kommt. Da hätte ich halt gerne 
eine Hausnummer wie lange so ein ReadFile(1 Datenbyte) im Durchschnitt 
dauert.

Vielen Dank soweit.
Nochmal.
Es ist ziemlich egal, was du oder Windows in deinem Programm machst. 
Solange du nicht mutwillig Unmengen an Rechenzeit verbrutzelst 
natürlich. Dein zeitbestimmender Flaschenhals ist die eigentliche 
Übertragung an der seriellen Schnittstelle. Im Vergleich zu dem, was 
sich an dieser Schnittstelle abspielt, ist alles andere völlig 
unwichtig. Und wenn du zwischen dem Senden zweier Bytes 3 Millionen 
quadratische Gleichungen löst, wirst du den Unterschied nicht merken 
oder messen können.
Oder anders ausgedrückt: Ob die Küche 5 oder 10 Sekunden zur 
Bereitstellung eines Menütellers benötigt ist völlig uninteressant, wenn 
der Kellner 2 Minuten braucht um es zum Gast zu bringen. In dieser Zeit 
stellt die Küche den nächsten Teller auf jeden Fall her, egal ob sie 5 
oder 10 Sekunden dafür braucht.
1
  LONGLONG  freq,start,stop,diff;
2
  double  time;
3

4
  HANDLE hProg = GetCurrentProcess();
5
  assert(hProg);
6
  assert(SetPriorityClass(hProg,REALTIME_PRIORITY_CLASS));
7

8
  hProg = GetCurrentThread();
9
  assert(hProg);
10
   assert(SetThreadPriority(hProg,THREAD_PRIORITY_HIGHEST));
11

12
  if(!QueryPerformanceFrequency((LARGE_INTEGER*)&freq))
13
  {
14
    printf("no PerformanceCounter,\n");
15
    exit (-2);
16
  }
17
  printf("freq is %I64u per sec.\n",freq);
18

19
  for(ByteData=0;ByteData<101;ByteData++)
20
  {
21
//    set = ByteData%6;
22
    set = ByteData;
23
    QueryPerformanceCounter((LARGE_INTEGER*)&start);
24
    Sleep(set);
25
    QueryPerformanceCounter((LARGE_INTEGER*)&stop);
26
    diff = stop - start;
27
    printf(" % 4u : ",set);
28
//    printf(" %I64u %I64u  %I64u ",start,stop,diff);
29
    time = diff;
30
    time /= freq;
31
//    printf(" %I64u %f ",diff,time);
32
    time *= 1000.0;
33
    printf(" %.3f ms",time);
34
    printf("\n");
35
  }
36
   fprintf(stderr,"\nHit any key.\n\n\n");
37
   getchar();
38
  exit(-1);

ich habe mal die Function sleep ausgemessen.
Ist das was du suchst?
OP
Hallo,

ich habe die Ursache für den schleichenden Workerthread gefunden. Die 
Fehlerursache war in der falschen bzw. nicht durchgeführten 
Konfiguration der Timeoutparameter begründet. Diese habe ich jetzt auf
1
COMMTIMEOUTS ctmo;
2
ctmo.ReadIntervalTimeout = MAXDWORD;
3
ctmo.ReadTotalTimeoutMultiplier = 0;
4
ctmo.ReadTotalTimeoutConstant = 0;
5
SetCommTimeouts(Device, &ctmo);

gestellt, damit ReadFile nicht im Timeout wartet (sofern keine Daten 
mehr kommen), sondern sofort zurückkehrt. Zusätzlich hab ich noch einen 
Fehler in meinen Synchronisations-Events gefunden und übertrage jetzt 
nicht jedes Byte einzeln sondern bis zu 256 pro Threaddurchlauf.

Das ganze flutscht jetzt um Größenordnungen besser. Die Abarbeitung 
eines "Kommunikationsablaufs" hat vorher gut 8-10 Sekunden gedauert. 
Nach der Überarbeitung <1 Sekunde.

Zwar war das hier nicht direkt die Problemlösung, hat mich jedoch auf 
den richtigen Lösungsweg gebracht. Vielen Dank soweit.

Antwort schreiben

Eine eigene Frage? Dieser Thread ist über 17 Jahre alt. Stell sie in einem eigenen Thread – dort lesen mehr Leute mit, und sie wird öfter und schneller beantwortet.

Neuen Thread starten

Eine Lösung, Ergänzung oder Rückmeldung zu diesem Thread? Dann antworte hier.

Formatierung
  • [c]C-Code[/c]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] – Link zu einem Artikel
  • Verweis auf einen anderen Beitrag: Rechtsklick auf dessen Beitrags-ID (#8078628), „Adresse kopieren“, in den Text einfügen

Mehr zur Formatierung

Längeren Sourcecode als Anhang, nicht in den Text. JPG nur für Fotos und Scans; Zeichnungen und Screenshots als PNG oder GIF. Siehe Bildformate.

Schon registriert? Anmelden

Wird nicht angezeigt. Wir schicken dir einen Link; sobald du damit bestätigst, erscheint dein Beitrag.

Mit dem Abschicken legst du einen kostenlosen Account an und erkennst die Nutzungsbedingungen und die Datenschutzerklärung an.