Forum: Mikrocontroller und Digitale Elektronik CAN Performance: µC vs Linux on ARM


von Mike (Gast)


Lesenswert?

Guten Morgen,

wir arbeiten an sich in der µC Welt. (32bit ~32-200MHz) und sehr oft mit 
CAN (bis zu 3 Schnittstellen meistens 250kB).
Für eine Neu-Entwicklung setzen wir nun erstmals ein ARM basierendes 
embdedded Linux Board ein. HW: GEA MX6UL @528MHz 128MB DDR3 SW: 
yocto-based embedded Linux an sich sehr schlank gehalten.
Nach den ersten Tests sieht es nun so aus, als würden wir es mit 
Standard-Libraries nicht schaffen auch nur einen 250k CAN Bus zu 
verarbeiten wenn er ohne CAN-Nachrichten Filter arbeitet. Wir wollten 
eigentlich in einer Ausbaustufe alle CAN Nachrichten uns ansehen, Daten 
daraus nehmen, Dinge berechnen und diese dann via ppp über UMTS 
versenden. Das ganze läuft mit python3 und python-can im SOCK_RAW Modus. 
Ein Thread wertet den CAN Socket aus und sendet die Messages via Queue 
an den Main-Auswerte Thread. Der wiederum in eine sqlite3 DB und ein 
weiterer Process dann in die Cloud. Funktioniert an sich prima so bis 
70% Buslast, danach beginnt das System dann instabil zu werden dh Queue 
vom socketTask baut sich auf und kann nicht so schnell abgearbeitet 
werden.
Wir haben nun wie gesagt solche Probleme in der 32bit ~100Mhz Welt µC 
ohne RTOS-Welt nicht und wundern uns nun etwas ob das mit ARM7 528MHz 
nun ein SW-Designfehler von uns ist oder ob das Linux+Task-Switching uns 
da einen Strich durch die Rechnung macht.

Vielen Dank für eure Unterstützung im Voraus
Mike

von Μαtthias W. (matthias) Benutzerseite


Lesenswert?

Hi

Ältlicher Kernel? (gerade beim flexcan ging in letzter Zeit einiges)
Uns gelingt die Auslastung von zwei CAN-Bussen a 1MBit/s auf einem iMX6 
ohne Paketverluste während noch eine grafikintensive Anwendung und 
Netzwerkkommunikation läuft. Also im Prinzip gehts.

Matthias

von dunno.. (Gast)


Lesenswert?

Μαtthias W. schrieb:
> Also im Prinzip gehts.

auch mit python? oder doch in einer richtigen programmiersprache? =)

von Μαtthias W. (matthias) Benutzerseite


Lesenswert?

dunno.. schrieb:
> Μαtthias W. schrieb:
>> Also im Prinzip gehts.
>
> auch mit python? oder doch in einer richtigen programmiersprache? =)

Ich würde mal vermuten das es auch in Python gehen sollte da dort ja nur 
noch von einem Socketinterface gelesen wird mit wenigen 10kByte/s was 
auch für Python kein Problem sein sollte. Aber unsere Anwendung ist in 
C++ geschrieben so das ich mit Python keine Erfahrung habe.

Ich würde als erstes mit top schauen wo da die große Last entsteht 
(Kernel, Python, sonstwas)

Matthias

von TestX (Gast)


Lesenswert?

Python, sqlite und eine 500MHz Gurke...da wundert ihr euch noch ?
In C mit in memory datenbank wäre es kein Problem...

von moep (Gast)


Lesenswert?

Mike schrieb:
> danach beginnt das System dann instabil zu werden dh Queue
> vom socketTask baut sich auf und kann nicht so schnell abgearbeitet
> werden.

Das heißt aber ja eigentlich, dass nicht die Kommunikation das Problem 
ist, sondern ihr die Daten nicht schnell genug verarbeitet bekommt, 
oder?

Du solltest herausfinden warum das System nicht dazu kommt die Daten 
abzuarbeiten.

Mal zwei mögliche Szenarien:

1. Der Empfang der Daten ist sehr aufwändig und dein Socket-Thread 
frisst dem Auswertthread die CPU-Zeit weg, sprich der Auswertethread 
kommt gar nicht mehr an die Reihe.

2. Der Empfang läuft mit überschaubarer Last, dafür rennt der 
Auswertethread bei fast 100% CPU-Zeit. Sprich deine "Auswertung" ist 
einfach zu langsam.

von Peter D. (peda)


Lesenswert?

Der CAN-Bus hat ~50% Overhead, d.h. bei 1MBaud ist die Nutzdatenrate 
~62kB.
Da klemmt also irgendwas bei Deiner Verarbeitung.

von Guido G. (nugglix)


Lesenswert?

Moin!

Irgendwann muss der Kernel die Daten ja mal schreiben, dann hakt es beim
schreiben in die DB, was dann die Queue voll macht.

Und Threads in Python sind eh keine gute Idee.

Stell doch erst mal fest, wo es langsam wird.

Was für ein Massenspeicher wird denn verwendet?
Wie wirkt der sich auf die Systemleistung aus?

Für den Einsteiger: mal top laufen lassen um zu sehen was
auf dem System passiert.

Ohne Code ist das meiste aber eh nur geraten.
Klar, den kann man nicht zeigen.
Aber somit ist die zu erhaltende Hilfe recht eingeschränkt.

Man kann mit Python auch auf kleinen Systemen gute Ergebnisse
erzielen, aber dafür muss man sowohl das System wie auch
Python gut kennen. Für ein Erstlingswerk klingt die Zielsetzung
schon etwas heftig.

Grüße

von Mike (Gast)


Lesenswert?

Hallo danke erstmal.

An sich der EmpfangsThread ist sehr schlank
1
    def _RxSocket(self):
2
        while self.rxSocketRun:
3
            cf, addr = self._can.recvfrom(16)
4
            self.rcvSocketQ.put(cf)
Die Auswertung ist dann aber schon aufwändiger, aber auch überschaubau, 
alle Msgs durchgehen daraus CAN Messages machen(könnt ich vielleicht 
einsparen), aus den Daten float berechnen und in die sqlite 
verspeichern.

TestX schrieb:
> Python, sqlite und eine 500MHz Gurke...da wundert ihr euch noch ?
> In C mit in memory datenbank wäre es kein Problem...

Gibt es dafür Beispiele? Kommen ja aus der c-Welt, zwar embedded aber 
das sollten wir hinbekommen.

moep schrieb:
> 2. Der Empfang läuft mit überschaubarer Last, dafür rennt der
> Auswertethread bei fast 100% CPU-Zeit. Sprich deine "Auswertung" ist
> einfach zu langsam.

So sieht es aus, Messages gehen ja "keine" verloren und die landen alle 
in der Q.

Μαtthias W. schrieb:
> Ältlicher Kernel? (gerade beim flexcan ging in letzter Zeit einiges)
3.14

Klingt also doch nach SW-Designfehler.. dh-> nachdem wir vielleicht in 
späterer Folge ein Display (mit der Gedanke war eigentlich Qt) 
anschließen wollen sieht das mit der CPU wohl und python schlecht aus 
--> C++?

Danke

von Mike (Gast)


Lesenswert?

Guido G. schrieb:
> Irgendwann muss der Kernel die Daten ja mal schreiben, dann hakt es beim
> schreiben in die DB, was dann die Queue voll macht.

Ist ein Nand-Flash System. Mittels Top schwer erkennbar ob es daran 
hackt oder in der Datenauswertung, da ja alles ein Thread ist, da müsst 
ich noch ein paar Dinge einbauen.

Der python3 Prozess (Hauptauswerte Task + Rcv Socket Thread) laufen so 
ziemlich bei 95%

von Lutz (Gast)


Lesenswert?

Also wenn in einem so frühen Stadium und beim Daddeln/Testen schon eine 
so hohe Auslastung auftritt, würde ich gleich auf C / C++ schwenken, 
zumal das ja beherrscht wird.

von Guido G. (nugglix)


Lesenswert?

Mike schrieb:
> Der python3 Prozess (Hauptauswerte Task + Rcv Socket Thread) laufen so
> ziemlich bei 95%

Das ist zu viel.
Bedenke das der Kernel und andere Prozesse auch CPU
benötigen.

Und Threads in Python sind für so etwas keine gute Idee.
Ich empfehle da mal etwas Quellenstudium.

Da Ihr ja Erfahrungen in C habt, wäre es deutlich einfacher
das ganze auf einige kleine Prozesse zu verteilen, die Ihr
in C bauen könnt.

Das "einfach" zum Laufen zu bringen ist sicher machbar,
aber vergleichsweise teuer.

Und bitte nicht vergessen: ein Linux-System macht noch andere
Sachen. Die auch mal prüfen bzw. bei Messungen berücksichtigen.

Grüße

von Henning L. (henning_l208)


Lesenswert?

Noch ein Hinweis zu SQLite. Das arbeitet normalerweise synchron, also 
ein INSERT wird als Transaktion ausgeführt und ist erst dann fertig, 
wenn die Daten sicher auf den Speicher geschrieben wurden. Das kann in 
deinen Fall relevant sein.

Siehe auch https://sqlite.org/faq.html#q19

von Mike (Gast)


Lesenswert?

Danke erstmal für die produktiven Antworten!

Hab mir mit cProfile mal genauer die Sache angesehen:
1
ncalls  tottime  percall  cumtime  percall filename:lineno(function)
2
     1663    7.310    0.004    7.310    0.004 {built-in method ioctl}
3
     9380    4.840    0.001    4.840    0.001 {method 'send' of '_socket.socket' objects}
4
     3863    3.847    0.001    3.876    0.001 {method 'execute' of 'sqlite3.Connection' objects}
5
      310    2.027    0.007    2.407    0.008 ThingPush.py:83(insert_data)
6
    39856    1.519    0.000    1.835    0.000 queue.py:93(empty)
7
    38193    1.508    0.000    4.330    0.000 queue.py:150(get)
8
      203    1.060    0.005    1.358    0.007 ThingPush.py:55(insert_command)
9
     7280    0.930    0.000    5.284    0.001 DRIVER_WTHING.py:306(SendS3Data)
10
     1663    0.926    0.001    7.601    0.005 Global_CAN.py:20(GetMessage)
11
    38195    0.793    0.000    1.254    0.000 threading.py:329(notify)
12
     3325    0.746    0.000    0.789    0.000 DRIVER_WTHING.py:155(CheckCANMessages)
13
     1746    0.488    0.000    0.488    0.000 {built-in method stat}
14
     9380    0.469    0.000    0.471    0.000 message.py:12(__init__)
15
    78049    0.441    0.000    0.614    0.000 queue.py:205(_qsize)
16
    38193    0.415    0.000    4.744    0.000 queue.py:189(get_nowait)
Die Timestamp info der Can Nichtricht braucht schon mal einiges an Zeit 
wie es aussieht
1
res = fcntl.ioctl(self._can, SIOCGSTAMP, struct.pack("@LL", 0, 0))
2
            seconds, microseconds = struct.unpack("@LL", res)
3
            timestamp = seconds + microseconds / 1000000

und an sich das db handling
1
try:
2
            with self._db_connection:
3
                self._result = self._db_connection.execute(self._query, (payload, timestamp, ))
4
        except Exception as ex:
5
            LOGGER.error(str(ex))
6
            LOGGER.error(traceback.format_exc())
7
            print (str(ex))
8
            print (traceback.format_exc())
9
10
        return self._result

Guido G. schrieb:
> Und Threads in Python sind für so etwas keine gute Idee.
> Ich empfehle da mal etwas Quellenstudium.
Kannst du mir dazu noch mehr Infos geben?

Lutz schrieb:
> würde ich gleich auf C / C++ schwenken,
> zumal das ja beherrscht wird.
Die Programmiersprache an sich schon, aber die verwendeten Packages 
sqlite, qt usw haben wir teilweise mit python schon verwendet, mit c/c++ 
nicht deshalb war eigentlich die Idee auf python zu setzen. An sich habe 
ich ja schon python Erfahrung aus der PC Welt und AnsiC aus der embedded 
dazwischen also c/C++ auf Linux ist eher Neuland

Guido G. schrieb:
> Ohne Code ist das meiste aber eh nur geraten.
> Klar, den kann man nicht zeigen.
> Aber somit ist die zu erhaltende Hilfe recht eingeschränkt.

Das ist nicht das Problem, der ganze Source ist aber auch nicht 
hilfreich da schon umfangreich

von Felix U. (ubfx)


Lesenswert?

Mike schrieb:
> An sich habe
> ich ja schon python Erfahrung aus der PC Welt und AnsiC aus der embedded
> dazwischen also c/C++ auf Linux ist eher Neuland

Die Methodik ist überall die gleiche. Es ist klar, dass du auf 500MHz 
nicht jedes erdenkliche convenience Feature (pack, queue, sqlite, ...) 
benutzen kannst, und dann noch einen hohen Durchsatz kriegst. Das selbe 
Problem hättest du in C++.

Da jetzt umzuschwenken wird dir höchstens minimale Performancezuwächse 
bringen (die ganze Hin- und Her Konvertiererei bei den Syscalls würde 
wegfallen). Der größte Zeitfresser ist eindeutig SQLite mit socket.send 
und Connection.execute. Das könnte man non-blocking ausführen hat dann 
aber wohl keine Gewähr, dass der Vorgang bis zur nächsten CAN-Message 
abgeschlossen ist. Als nächstes die diversen queue-Operationen, hier 
wäre vielleicht ein statischer Ringbuffer besser, dessen Inhalt man alle 
X Messages gesammelt an SQLite übergibt, das dürfte die Zeit pro 
INSERTeter row im Schnitt noch wesentlich senken.

von Guido G. (nugglix)


Lesenswert?

Mike schrieb:
> Guido G. schrieb:
>> Und Threads in Python sind für so etwas keine gute Idee.
>> Ich empfehle da mal etwas Quellenstudium.
> Kannst du mir dazu noch mehr Infos geben?

$Suchmaschine: python gil

> Lutz schrieb:
>> würde ich gleich auf C / C++ schwenken,
>> zumal das ja beherrscht wird.
> Die Programmiersprache an sich schon, aber die verwendeten Packages
> sqlite, qt usw haben wir teilweise mit python schon verwendet, mit c/c++
> nicht deshalb war eigentlich die Idee auf python zu setzen. An sich habe
> ich ja schon python Erfahrung aus der PC Welt und AnsiC aus der embedded
> dazwischen also c/C++ auf Linux ist eher Neuland

Das ist mal schlecht.
Ihr könnt nicht so richtig Python und auch nicht so richtig
C/C++ unter Linux.
Wie soll das gehen?

> Guido G. schrieb:
>> Ohne Code ist das meiste aber eh nur geraten.
>> Klar, den kann man nicht zeigen.
>> Aber somit ist die zu erhaltende Hilfe recht eingeschränkt.
>
> Das ist nicht das Problem, der ganze Source ist aber auch nicht
> hilfreich da schon umfangreich

Möp, falsch.
Der Source zeigt was wirklich passiert.
Prosa ist da wenig hilfreich.

Btw, wer macht denn da busy-wait auf die Queue?
Siehe Queue.get_nowait, Queue.empty etc.
Code würde schon helfen... seufz

von St. D. (st_d)


Lesenswert?

Wenn solche 'triviale' Aufgaben mit Hochsprachen wie Python zu erledigen 
wäre, wäre C wahrscheinlich bald obsolet, weil sind die ~500MHz ARM SoCs 
nicht mehr viel teurer als uCs...

von Mike (Gast)


Lesenswert?

Mike schrieb:
> Die Timestamp info der Can Nichtricht braucht schon mal einiges an Zeit
> wie es aussiehtres = fcntl.ioctl(self._can, SIOCGSTAMP,
> struct.pack("@LL", 0, 0))
>             seconds, microseconds = struct.unpack("@LL", res)
>             timestamp = seconds + microseconds / 1000000

hab das rausgenommen aber es gibt den call noch immer. Kann sein, dass 
dies ein interner Call ist, der cProfile nicht genau aufschlüsselt? 
Würde von der Anzahl her ungefährt dem senden entsprechen, der 
Auswerte-Task muss auch einige CAN Nachrichten schicken um alle zu 
empfangen.
1
     2089    7.379    0.004    7.379    0.004 {built-in method ioctl}
2
     9989    6.793    0.001    6.793    0.001 {method 'send' of '_socket.socket' objects}
Empfangen werden ja viel mehr (~44000 in 40sek) also daher kann der 
ioctl nicht kommen. Bremst mich das senden der CAN Nachrichten auch ein? 
Mach das im Auswerte-Thread mit dem gleichen Socket mit dem ich 
empfange:
1
def _SendMessage(self, m):
2
      data = m.data.ljust(8, b'\x00')
3
      arbitration_id = m.arbitration_id
4
      if m.id_type:
5
          arbitration_id |= 0x80000000
6
            
7
      msg = struct.pack("=IB3x8s", arbitration_id, m.dlc, data)
8
      self._can.send(msg)

Felix U. schrieb:
> Da jetzt umzuschwenken wird dir höchstens minimale Performancezuwächse
> bringen.
Der Meinung war ich bei uns intern auch, da ich python an sich schon 
auch für performant halte.

Felix U. schrieb:
> Der größte Zeitfresser ist eindeutig SQLite mit socket.send und
> Connection.execute.
Geht wohl in die Richtung..

von Mike (Gast)


Lesenswert?

Guido G. schrieb:
> Das ist mal schlecht.
> Ihr könnt nicht so richtig Python und auch nicht so richtig
> C/C++ unter Linux.
> Wie soll das gehen?

Wenn alle Menschen nur das machen was sie können würden wir wohl noch in 
der Ursuppe schwimmen.

Guido G. schrieb:
> Btw, wer macht denn da busy-wait auf die Queue?
> Siehe Queue.get_nowait, Queue.empty etc.
> Code würde schon helfen... seufz

folgt

von Felix U. (ubfx)


Lesenswert?

Mike schrieb:
> Kann sein, dass
> dies ein interner Call ist,

Ja. Das ist ein Call in Verbindung mit irgendeinem Socket descriptor.

Mike schrieb:
> Bremst mich das senden der CAN Nachrichten auch ein?
> Mach das im Auswerte-Thread mit dem gleichen Socket mit dem ich
> empfange:

Vom senden hatte ich bisher gar nichts gelesen. Habe ich das jetzt 
richtig verstanden, dass du die Nachricht unpackst, dann einzeln an 
SQLite übergibst und dann einzeln wieder packst und wieder auf einem CAN 
socket rausschickst?

von Guido G. (nugglix)


Lesenswert?

Mike schrieb:
> Guido G. schrieb:
>> Das ist mal schlecht.
>> Ihr könnt nicht so richtig Python und auch nicht so richtig
>> C/C++ unter Linux.
>> Wie soll das gehen?
>
> Wenn alle Menschen nur das machen was sie können würden wir wohl noch in
> der Ursuppe schwimmen.

Das beantwortet die Frage nicht.
Die war durchaus ernst gemeint.

von Mike (Gast)


Angehängte Dateien:

Lesenswert?

Anbei der Can Treiber (_init_.py) welcher in der _RxSocket in die 
Queue für die Auswertung puscht.

die RxTask wird vom Auswerte Thread aufgerufen und generiert CAN 
Messages und schiebt diese in eine weitere Q.

Der Main-Task wertet die CAN Messages aus der Nachrichten Q folgend aus. 
Der ist leider Teil eines großen Skript, dass andere Dinge auch noch 
macht
1
def CheckCANMessages(messages, ids = [0x18ff28]):
2
    ret = []
3
    for canIndex, msgs in messages:
4
        for m in msgs:
5
            mid = m.arbitration_id >> 8
6
            if m.arbitration_id >> 8 in ids:
7
                sender = "WTHING_CAN%d@"%canIndex+ str(m.arbitration_id&0xff)
8
                if mid == 0x18ff28:#IOT DP Message
9
                    ret.append(Thing_DataPoint.ReturnDP(sender, m.data[0:6]))
10
                else:
11
                    if ids != [0x18ff28]:
12
                        ret.append(m)
13
    return ret
14
15
16
def ReturnDP(sender, dat):
17
    dpnr = dat[0]+(dat[1]<<8)
18
19
    if dpnr & 0x8000:
20
        error = True
21
    else:
22
        error = False
23
    dpnr &= ~0x8000
24
    dpnr = "DP"+str(dpnr)
25
26
    if not error:#valid dp value message
27
        value = dat[2]+(dat[3]<<8)+(dat[4]<<16)+(dat[5]<<24)
28
        if value > 2147483647:
29
            value = float((4294967296-value)*(-1))
30
        else:
31
            value = float(value)
32
        return (sender, dpnr,value,error )
33
    else:
34
        return (sender, dpnr,float(dat[2]),error )

Und anbei noch das Script, welches dann in die sqlite schiebt, da wird 
an sich das result von der CheckCANMessages einzeln inserted.

von Mike (Gast)


Lesenswert?

Felix U. schrieb:
> Vom senden hatte ich bisher gar nichts gelesen. Habe ich das jetzt
> richtig verstanden, dass du die Nachricht unpackst, dann einzeln an
> SQLite übergibst und dann einzeln wieder packst und wieder auf einem CAN
> socket rausschickst?

Nein ich muss nur um die CAN Bus Teilnehmer zu bedienen auch Nachrichten 
CAN Nachrichten senden.

Guido G. schrieb:
> Das beantwortet die Frage nicht.
> Die war durchaus ernst gemeint.

Sorry, hab Sie nicht für ernst genommen. Es geht im Moment eh nicht, ist 
aber eine Entwicklung die wir angehen möchten. µC+Ansii C reicht unseren 
Kunden bald nicht mehr, da eben IoT usw. aufkommt, dh für uns 
Netzwerkschnittstellen, Dateisystem usw.

von Felix U. (ubfx)


Lesenswert?

Das ist echt programmiert als hättet ihr 4 Kerne. Ich würde den ganzen 
Ballast mal rausschmeißen und in einem Thread arbeiten, der Kernel 
cached ja sowieso ein paar Messages für euch, da hat es keinen Zweck die 
noch drei mal zwischenzuspeichern in verschiedenen Threads, die dann 
doch alle nur nacheinander ablaufen. (Das wäre in C fast genau so 
unperformant)

Mike schrieb:
> Nein ich muss nur um die CAN Bus Teilnehmer zu bedienen auch Nachrichten
> CAN Nachrichten senden.

Ist es bei CAN nicht so, dass dann erst gewartet werden muss, bis der 
Bus frei ist? Bei einem blocking Call kann man da auch ordentlich Zeit 
verschwenden.

von Mike (Gast)


Lesenswert?

Felix U. schrieb:
> Das ist echt programmiert als hättet ihr 4 Kerne. Ich würde den ganzen
> Ballast mal rausschmeißen und in einem Thread arbeiten, der Kernel
Wie gesagt, kenn python ja eher aus der PC Welt, ist wohl wieder ein 
umdenken notwendig auf embedded.

Felix U. schrieb:
> drei mal zwischenzuspeichern in verschiedenen Threads
Versteh ich, einen Thread muss ich aber behalten, da ich sonst 
Nachrichten verliere, die Zwischen Q werd ich mir wohl auch sparen und 
bin am schauen ob ich das umrechnen in CANMessage Type der python-can 
lib einspare. Das kommt aber daher, da ich eigentlich am PC entwickle 
dort aber da Windows nicht SocketCAN sonder PCAN HW+Treiber, jetzt war 
der Gedanke alles in python-CAN Messages umzukopieren, damit die 
Applikation dann immer gleiche Daten hat.

Felix U. schrieb:
> Ist es bei CAN nicht so, dass dann erst gewartet werden muss, bis der
> Bus frei ist? Bei einem blocking Call kann man da auch ordentlich Zeit
> verschwenden.
Dachte, dass macht der Linux Treiber dann und der socket send ist none 
blocking.

von Guido G. (nugglix)


Lesenswert?

Jo, sieht nicht gerade gut aus.

Das unsägliche logging durch was kleineres ersetzen.
Das frisst CPU wie ein Großer.

Und möglichst das Schreiben auf SD vermeiden, das bremst ungemein.
Besonders weil ja das sqlite auch schreibt.
Wenn Ihr schon dabei seit, auch gleich das Logging der anderen
Dienste runter drehen.

Ich kann jetzt auch keinen Zusammenhang zw. IoT und zwangsweise
Python auf mini-Systemen erkennen. Aber wenn man meint...

> Das ist echt programmiert als hättet ihr 4 Kerne.
Bringt bei Python so erstmal nix, da keine 4 Kerne verwendet werden 
würden.

Um es mal deutlich zu sagen:
Das ganze ist schon sehr in der Ecke: falsches Werkzeug für die Aufgabe.

PS: Es liest sich so, als ob das mit den Threads in Python noch nicht 
angekommen wäre.

von Mike (Gast)


Lesenswert?

Guido G. schrieb:
> Das unsägliche logging durch was kleineres ersetzen.
> Das frisst CPU wie ein Großer.

Welches logging meinst du? Wird ja nur bei exceptions geloggt?


Μαtthias W. schrieb:
> Uns gelingt die Auslastung von zwei CAN-Bussen a 1MBit/s auf einem iMX6
> ohne Paketverluste während noch eine grafikintensive Anwendung und
> Netzwerkkommunikation läuft. Also im Prinzip gehts.
Unter python? iMX6 gibt es ja auch viele?!

Somit Fazit:
An sich unter python vorstellbar, oder SW-Designfehler und es müsste 
Richtung C/C++ gehen.
SQLite schaue ich mir auf jeden Fall an, dass dürfte ein ziemlicher 
Bottlenack sein. Aber vom Gefühl her würde ich sagen, dass wir selbst 
wenn wir da verbessern noch immer grenzwärtig mit der Performance sind.

von Lutz (Gast)


Lesenswert?

Mike schrieb:
> Felix U. schrieb:
>> Ist es bei CAN nicht so, dass dann erst gewartet werden muss, bis der
>> Bus frei ist? Bei einem blocking Call kann man da auch ordentlich Zeit
>> verschwenden.
> Dachte, dass macht der Linux Treiber dann und der socket send ist none
> blocking.

CAN ist grundsätzlich kollisionssicher (Stichwort Arbitrierung). Das 
stellt der CAN-Controller (in unabhängiger Hardware) sicher, sonst 
erfüllt er die CAN-Spec nicht. Wenn das ein Treiber machen sollte, wäre 
es mit dem Zeitmanagement wohl Asche.

von Felix U. (ubfx)


Lesenswert?

Mike schrieb:
> einen Thread muss ich aber behalten, da ich sonst
> Nachrichten verliere,

Woher weißt du das? Du verlierst doch jetzt auch schon Pakete. Versuch 
doch mal in einer simplen Schleife non blocking alle CAN-Messages die 
momentan in der Kernel-Queue sind auszulesen, dann deinen send-Kram zu 
machen und dann alle Messages in EINEM query an SQLite zu passen, und 
dann wieder von vorne.

von Mike (Gast)


Lesenswert?

Lutz schrieb:
> CAN ist grundsätzlich kollisionssicher (Stichwort Arbitrierung). Das
> stellt der CAN-Controller (in unabhängiger Hardware) sicher, sonst
> erfüllt er die CAN-Spec nicht. Wenn das ein Treiber machen sollte, wäre
> es mit dem Zeitmanagement wohl Asche.

Das ist mir schon klar, aber ich war bis jetzt der Meinung :
1
def _SendMessage(self, m):
2
      data = m.data.ljust(8, b'\x00')
3
      arbitration_id = m.arbitration_id
4
      if m.id_type:
5
          arbitration_id |= 0x80000000
6
            
7
      msg = struct.pack("=IB3x8s", arbitration_id, m.dlc, data)
8
      self._can.send(msg)
Das self._can.send(msg) die Daten dem Linux CAN-Treiber übergibt der 
buffert das in dem Ringbuffer, dafür hab ich auch die txqueuelen 1000 
rauf gedreht und der kümmert sich dann um das Versenden und die Funktion 
send ist somit none-Blocking. Ihr dürft mich gerne etwas anderem 
belehren, wenn dem Nicht der Fall ist, ist auch das ein ziemlicher 
Bottleneck.

von Guido G. (nugglix)


Lesenswert?

Mike schrieb:
> Guido G. schrieb:
>> Das unsägliche logging durch was kleineres ersetzen.
>> Das frisst CPU wie ein Großer.
>
> Welches logging meinst du? Wird ja nur bei exceptions geloggt?

Woher soll ich das wissen? Euer Code...

Es ist ein allgemeiner Rat.
Das Zeug ist halt bloated ohne Ende.

Keine Kommentare zum Logging der anderen Dienste? Tz tz tz...

> Somit Fazit:
> An sich unter python vorstellbar, oder SW-Designfehler und es müsste
> Richtung C/C++ gehen.

Ja, b) ist z.Z. mein Favorit.

Auf die Entfernung kann man da nichts ausrichten.
Ich wünsche Euch dann mal viel Glück.

von Mike (Gast)


Lesenswert?

Felix U. schrieb:
> Woher weißt du das? Du verlierst doch jetzt auch schon Pakete

Packete verliere ich so keine (Zähler und mit PCAN am Windows PC gegen 
gecheckt), die landen alle in der Q nur irgendwann stirbt der ganze 
Prozess da die Q so groß wird da der andere Thread zu wenige get schafft 
und das Linux den ganzen Prozess killt.

von Mike (Gast)


Lesenswert?

Guido G. schrieb:
> Auf die Entfernung kann man da nichts ausrichten.
> Ich wünsche Euch dann mal viel Glück.

Danke für die sachliche Unterstützung, und die "Ihr seit Looser und 
Finger weg davon" Kommenentare hab ich auch gelesen.

von Felix U. (ubfx)


Lesenswert?

Mike schrieb:
> Packete verliere ich so keine (Zähler und mit PCAN am Windows PC gegen
> gecheckt), die landen alle in der Q nur irgendwann stirbt der ganze
> Prozess da die Q so groß wird

Netto verlierst du also natürlich Pakete. Ob die jetzt im Kernel oder in 
deinem Prozess verloren gehen ist ja erst mal egal.

Mike schrieb:
> da der andere Thread zu wenige get schafft

Und das könntest du - wie gesagt - beheben, indem du mehrere Messages 
gleicheitig INSERTest.

von Guido G. (nugglix)


Lesenswert?

Mike schrieb:
> Guido G. schrieb:
>> Auf die Entfernung kann man da nichts ausrichten.
>> Ich wünsche Euch dann mal viel Glück.
>
> Danke für die sachliche Unterstützung, und die "Ihr seit Looser und
> Finger weg davon" Kommenentare hab ich auch gelesen.

Huh?
Die falschen Pillen eingeworfen?

Dir ist schon klar das "das Forum" nicht magisch Euren Kram
richten kann?

Ich habe versucht klar zu stellen, was Ihr bezogen auf
das Stück Software mal untersuchen solltet.
Dazu kam nur Geschwaller.

Ohne das System zu kennen und auch messen zu können,
ist das halt sowas wie Fern-Reki, seeeehr esoterisch.
Das ist nicht meines.

Und wenn man kundtut, das Eure geringe Erfahrung mit der einen
oder anderen Programmiersprache schon auffällt, ist das nur ein
Hinweis das es evtl. bessere Lösungsmöglichkeiten gibt.
Wenn Geld allerdings keine Rolle spielt...

So, ich geb' nu Ruhe.

von Mike (Gast)


Lesenswert?

Guido G. schrieb:
> Huh?
> Die falschen Pillen eingeworfen?
>
> Dir ist schon klar das "das Forum" nicht magisch Euren Kram
> richten kann?

No comment.

Guido G. schrieb:
> Und wenn man kundtut, das Eure geringe Erfahrung mit der einen
> oder anderen Programmiersprache schon auffällt, ist das nur ein
> Hinweis das es evtl. bessere Lösungsmöglichkeiten gibt.
> Wenn Geld allerdings keine Rolle spielt...
>
> So, ich geb' nu Ruhe.

No try, no fail, no progress.

Und wie gesagt, danke vor allem für deine sachlichen Kommentare.

von Simon K. (simon) Benutzerseite


Lesenswert?

Hast du denn nach mehrfachem Hinweis dich jetzt mit dem Python Global 
Interpreter Lock (GIL) beschäftigt?
Multithreading hat unter Python halt seine Limits. Probiere es mal mit 
Multiprocessing.

von Mike (Gast)


Lesenswert?

Simon K. schrieb:
> Hast du denn nach mehrfachem Hinweis dich jetzt mit dem Python Global
> Interpreter Lock (GIL) beschäftigt?
> Multithreading hat unter Python halt seine Limits. Probiere es mal mit
> Multiprocessing.

Danke, hab es am Radar.. Vielleicht ganz kurz was bei Single-CPU da der 
große Benefit ist?

von Jim M. (turboj)


Lesenswert?

Simon K. schrieb:
> Multithreading hat unter Python halt seine Limits. Probiere es mal mit
> Multiprocessing.

Irks. Er hat nur einen CPU Kern, da sind Kontextwechsel und IPC realtiv 
teuer. Bei Threads müssen er die Daten nicht zwischen Prozessen kopiert 
werden.

Zu der Python vs. C Debatte fällt mr das hier ein (alter 24C3 Vortrag):
https://youtu.be/Vzh8F408CJg?t=1213
> "Das läuft nicht, das taucht im top nicht auf..".

Pyhton ist grade bei den sehr schlanken CPUs in IoT eine eher schlechte 
Wahl IMHO, da reicht die Performance doch eher nur in C/C++.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.