CAN-Trace (ASCII) Converter, Performanceprobleme

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
xoxox
User
Beiträge: 12
Registriert: Dienstag 11. September 2007, 13:51

Hallo,
aus der Not heraus habe ich auf die Schnelle einen Converter für ASCII-Logdateien geschrieben. Es sind Cancorder CAN-Trace Logs, die in was für Canape Lesbares gewandelt werden.

Eine zu konvertierende Datei sieht so aus:
// Tracefile imported from CANCorder device on
// Mon Aug 27 14:15:15 2007
// Tracerecord from blue PiraT data logger
// Number of records : 245626
// Trace duration : 0:04:00
// Started trace at : Tue Aug 21 12:03:43 2007
// Stopped trace at : Tue Aug 21 12:07:43 2007

00:00:00.029.0 CAN2 Rx ---- Pre ce 51 04 54 04 4e 04 4e 04
00:00:00.029.3 CAN2 Rx ---- Pre 128 6e 35 e0 e0 00 c7 7e ff
00:00:00.029.5 CAN2 Rx ---- Pre c9 de ff 10 00 90 1c 4b 12
00:00:00.031.3 CAN2 Rx ---- Pre 118 00 80 17 00 80 fa ff 0e
00:00:00.031.6 CAN2 Rx ---- Pre 11f 08 01 00 00 d7 ff 44 69
00:00:00.032.5 CAN2 Rx ---- Pre 80 00 00 c4 ed 00
Eine konvertierte Datei sieht so aus:
date Tue Aug 21 12:03:43 2007
base hex timestamps absolute
0.0000 2 ce Rx d 8 51 04 54 04 4e 04 4e 04
0.0003 2 128 Rx d 8 6e 35 e0 e0 00 c7 7e ff
0.0005 2 c9 Rx d 8 de ff 10 00 90 1c 4b 12
0.0023 2 118 Rx d 8 00 80 17 00 80 fa ff 0e
0.0026 2 11f Rx d 8 08 01 00 00 d7 ff 44 69
0.0035 2 80 Rx d 5 00 00 c4 ed 00
Also nichts Wildes an sich. Die einzelnen Reihen sind vertauscht, der Zeitstempel ist anders aufgebaut.

Mein Programm funktioniert auch, nur beim Ausführen lastet es einen CPU-Lern voll aus (C2D, 2GB Ram, WinXP). Ich kann nicht ganz nachvollziehen, was daran soviel Rechenzeit frisst.

Ich habe Windows in Verdacht, bin mir aber nicht sicher, ob es evtl. an meinem Programm liegt. Könnt ihr mal bitte mal drüber schauen?

Code: Alles auswählen

import csv
import sys
from os import path

if len(sys.argv) == 2:
    infile_name  = sys.argv[1]
    tmp = path.splitext(infile_name)
    outfile_name = ''.join([tmp[0],'_conv',tmp[1]])
else:
    print "Aufruf: converter [Trace-Datei]"
    sys.exit()

flag_1 = True
out_str = str()
output = open(outfile_name,'w')

lines = csv.reader(open(infile_name, "r"),delimiter=' ', skipinitialspace = True)
for line in lines:

    if '//' in line[0]:
        if 'Started' in line[1]:
             date = '%s %s %s %s %s %s' % ('date',line[5],line[6],line[7],line[8],line[9])

    elif line[0]:
        try:
            tmp = line[0].split(':')
            tmp1 = tmp[2].split('.')

            hour = int(tmp[0]) * 3600
            min = int(tmp[1]) * 60
            sec =  int(tmp1[0])
            msec = float(''.join(['0.',tmp1[1],tmp1[2]]))

            if flag_1:
                flag_1 = False
                output.write(date+'\n')
                output.write('base hex timestamps absolute\n')
                offset = hour + min + sec + msec

            timestamp =  '%.4f' % (hour+min+sec+msec-offset)
            can_num = line[1][-1:]
            can_id = line[5].rjust(3)
            direction = line[2]
            unknown1 = 'd'
            data_len =  len(line[6:])
            data =  ' '.join(line[6:])

            output.write('%s %s %s %s %s %s %s\n' % (timestamp, can_num, can_id, direction, unknown1, data_len, data))

        except:
            output.write(''.join(line))

output.close()

BlackJack

Ich verstehe die Frage nicht so ganz ─ jedes Programm lastet im Regelfall die CPU voll aus, wenn es nicht auf Daten von aussen wartet oder künstlich zum warten gezwungen wird.
Benutzeravatar
mkesper
User
Beiträge: 919
Registriert: Montag 20. November 2006, 15:48
Wohnort: formerly known as mkallas
Kontaktdaten:

In der Doku zu csv steht, daß man die Files binary öffen muß, wenn das System das unterstützt.
Zur CPU-Auslastung: du könntest den Task mit niedrigerer Priorität starten, dann nimmt er sich zwar 100% CPU, wenn nichts zu tun ist, aber nicht, wenn andere Arbeiten anstehen. Oder jede zweite Zeile auf einen anderen Thread verteilen, dann werden beide CPUs zu 100% ausgelastet. :)
Das Verwirrende ist, daß die ganzen Programme, die man gemeinhin auf einem Desktopsystem startet, die meiste Zeit einfach nur warten und daher auch keine CPU-Last erzeugen.
xoxox
User
Beiträge: 12
Registriert: Dienstag 11. September 2007, 13:51

In der Doku zu csv steht, daß man die Files binary öffen muß, wenn das System das unterstützt.
Binär-Modus für ASCII-Dateien?

Ich sollte dazu sagen, dass bei ~29MB Datei das Programm fast 30s beschäftigt ist. Und das eben bei voller CPU-Auslastung.

Wo wird denn da die Rechenzeit verbraten? Ein paar Spalten zu tauschen, ein paar String-Operationen, das kann doch net soviel Rechenzeit kosten, oder?
BlackJack

CSV Dateien sind keine Textdateien in dem Sinne, das Felder wirklich jedes Byte enthalten dürfen, inklusive '\n' und '\r' in beliebigen Kombinationen. Und wenn die Datei im Textmodus geöffnet wird, dann werden diese Bytes eventuell beim einlesen vom Betriebssystem bzw. der C-Laufzeitbibliothek verändert. Windows tut so etwas zum Beispiel.

Was die Laufzeit angeht: Wenn Du wissen willst, wo am meisten verbraten wird, kannst Du Dich mal mit dem `profile`-Modul beschäftigen.
xoxox
User
Beiträge: 12
Registriert: Dienstag 11. September 2007, 13:51

Ich hab Profile mal über die Kommandozeile laufen lassen.
Aber sehr viel kann ich daraus nicht lesen...

Code: Alles auswählen

         3170281 function calls in 25.940 CPU seconds

   Ordered by: standard name

   ncalls  tottime  percall  cumtime  percall filename:lineno(function)
        1    0.000    0.000   25.940   25.940 <string>:1(<module>)
        1   17.986   17.986   25.937   25.937 converter.py:1(<module>)
        1    0.000    0.000    0.000    0.000 csv.py:104(DictWriter)
        1    0.000    0.000    0.000    0.000 csv.py:138(Sniffer)
        1    0.000    0.000    0.000    0.000 csv.py:24(Dialect)
        1    0.000    0.000    0.000    0.000 csv.py:4(<module>)
        1    0.000    0.000    0.000    0.000 csv.py:55(excel)
        1    0.000    0.000    0.000    0.000 csv.py:65(excel_tab)
        1    0.000    0.000    0.000    0.000 csv.py:71(DictReader)
        1    0.000    0.000    0.000    0.000 ntpath.py:183(splitext)
        2    0.000    0.000    0.000    0.000 {_csv.register_dialect}
        1    0.002    0.002   25.940   25.940 {execfile}
   452894    0.898    0.000    0.898    0.000 {len}
        1    0.000    0.000    0.000    0.000 {max}
        1    0.003    0.003    0.003    0.003 {method 'close' of 'file' objects}
        1    0.000    0.000    0.000    0.000 {method 'disable' of '_lsprof.Profiler' objects}
   905789    2.037    0.000    2.037    0.000 {method 'join' of 'str' objects}
        3    0.000    0.000    0.000    0.000 {method 'rfind' of 'str' objects}
   452893    1.147    0.000    1.147    0.000 {method 'rjust' of 'str' objects}
   905788    2.308    0.000    2.308    0.000 {method 'split' of 'str' objects}
   452896    1.553    0.000    1.553    0.000 {method 'write' of 'file' objects}
        2    0.006    0.003    0.006    0.003 {open}
BlackJack

Naja, nach Namen sortiert anzeigen lassen ist vielleicht nicht so zielführend. Besser wäre es das Programm etwas sauberer in Funktionen aufzuteilen und dann zu sehen da am meisten Zeit varbraucht wird, und womit die verbraucht wird.

Hier ist mal eine Variante des Programms, die viel Gebrauch von Generatorfunktionen macht: http://paste.pocoo.org/show/4019/
xoxox
User
Beiträge: 12
Registriert: Dienstag 11. September 2007, 13:51

Uff, vielen Dank für die Arbeit Blackjack.
Ich verstehe zwar erstmal nur die Hälfte von dem Code, aber ich werde mich da mal durch arbeiten.
Antworten